Add SQLMapCLI - Beautiful CLI wrapper with Rich UI

Co-authored-by: GilbertKrantz <90319182+GilbertKrantz@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-01-05 18:14:36 +00:00
parent 84211142a8
commit 7129810b7c
2 changed files with 500 additions and 0 deletions

View File

@ -25,6 +25,64 @@ sqlmap works out of the box with [Python](https://www.python.org/download/) vers
Usage
----
### SQLMap CLI - Beautiful Automated Testing 🎨
**NEW**: We now have a beautiful CLI wrapper that automates comprehensive SQL injection testing in a single command!
#### Quick Start
Install dependencies:
```bash
pip install -r requirements.txt
```
#### Examples
**Quick scan** (default settings):
```bash
python sqlmapcli.py -u "http://example.com/page?id=1"
```
**Comprehensive scan** (tests all risk and level combinations):
```bash
python sqlmapcli.py -u "http://example.com/page?id=1" --comprehensive
```
**Custom level and risk**:
```bash
python sqlmapcli.py -u "http://example.com/page?id=1" --level 3 --risk 2
```
**Interactive mode**:
```bash
python sqlmapcli.py --interactive
```
#### Features
**Beautiful output** with Rich library - panels, tables, progress bars
**One-line comprehensive testing** - test all risk/level combinations automatically
📊 **Clear result summaries** - vulnerability tables with color-coded findings
🎯 **Interactive mode** - guided prompts for easy testing
⏱️ **Progress tracking** - see exactly what's being tested in real-time
#### CLI Options
```
-u, --url Target URL
--comprehensive Run all risk/level combinations (1-3 risk, 1-5 levels)
--level {1-5} Test level (default: 1)
--risk {1-3} Test risk (default: 1)
--max-level {1-5} Maximum level for comprehensive scan
--max-risk {1-3} Maximum risk for comprehensive scan
--technique SQL injection techniques (default: BEUSTQ)
-i, --interactive Interactive mode
```
---
### Original SQLMap Usage
To get a list of basic options and switches use:
python sqlmap.py -h

442
sqlmapcli.py Executable file
View File

@ -0,0 +1,442 @@
#!/usr/bin/env python3
"""
SQLMap CLI - A beautiful CLI wrapper for sqlmap
Automates comprehensive SQL injection testing with a single command
"""
import subprocess
import sys
import argparse
import time
import re
from pathlib import Path
from typing import List, Dict, Tuple
from datetime import datetime
try:
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TimeElapsedColumn
from rich.live import Live
from rich.layout import Layout
from rich.text import Text
from rich.prompt import Prompt, Confirm
from rich import box
from rich.style import Style
except ImportError:
print("Error: 'rich' library is required. Install it with: pip install rich")
sys.exit(1)
console = Console()
SQLMAP_PATH = Path(__file__).parent / "sqlmap.py"
# SQL injection techniques
TECHNIQUES = {
'B': 'Boolean-based blind',
'E': 'Error-based',
'U': 'Union query-based',
'S': 'Stacked queries',
'T': 'Time-based blind',
'Q': 'Inline queries'
}
class SQLMapCLI:
def __init__(self):
self.console = Console()
self.results = {
'total_tests': 0,
'vulnerabilities': [],
'start_time': None,
'end_time': None,
'target': None
}
def print_banner(self):
"""Display a beautiful banner"""
banner = """
CLI - Automated SQL Injection Testing
"""
self.console.print(banner, style="bold cyan")
self.console.print(
Panel(
"[yellow]⚠️ Legal Disclaimer: Only use on targets you have permission to test[/yellow]",
border_style="yellow",
box=box.ROUNDED
)
)
self.console.print()
def run_sqlmap_test(self, url: str, level: int, risk: int, technique: str = "BEUSTQ",
batch: bool = True, extra_args: List[str] = None) -> Tuple[bool, str]:
"""Run sqlmap with specified parameters"""
cmd = [
sys.executable,
str(SQLMAP_PATH),
"-u", url,
f"--level={level}",
f"--risk={risk}",
f"--technique={technique}",
"-v", "1"
]
if batch:
cmd.append("--batch")
if extra_args:
cmd.extend(extra_args)
try:
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=600 # 10 minute timeout per test
)
return result.returncode == 0, result.stdout + result.stderr
except subprocess.TimeoutExpired:
return False, "Test timed out after 10 minutes"
except Exception as e:
return False, str(e)
def parse_results(self, output: str) -> Dict:
"""Parse sqlmap output for vulnerabilities"""
vulns = []
# Look for vulnerability indicators
if "sqlmap identified the following injection point" in output:
# Extract injection details
lines = output.split('\n')
for i, line in enumerate(lines):
if "Parameter:" in line:
param = line.split("Parameter:")[1].strip()
if "Type:" in line:
vuln_type = line.split("Type:")[1].strip()
if i + 1 < len(lines) and "Title:" in lines[i + 1]:
title = lines[i + 1].split("Title:")[1].strip()
vulns.append({
'parameter': param if 'param' in locals() else 'Unknown',
'type': vuln_type,
'title': title
})
# Check for backend DBMS detection
backend_dbms = None
if "back-end DBMS:" in output.lower():
for line in output.split('\n'):
if "back-end DBMS:" in line.lower():
backend_dbms = line.split(":", 1)[1].strip()
break
return {
'vulnerabilities': vulns,
'backend_dbms': backend_dbms,
'is_vulnerable': len(vulns) > 0 or "vulnerable" in output.lower()
}
def comprehensive_scan(self, url: str, max_level: int = 5, max_risk: int = 3,
techniques: str = "BEUSTQ"):
"""Run comprehensive scan with all levels and risks"""
self.results['target'] = url
self.results['start_time'] = datetime.now()
# Create results table
results_table = Table(title="Scan Results", box=box.ROUNDED)
results_table.add_column("Level", style="cyan", justify="center")
results_table.add_column("Risk", style="yellow", justify="center")
results_table.add_column("Status", justify="center")
results_table.add_column("Findings", style="magenta")
total_tests = max_level * max_risk
test_count = 0
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
BarColumn(),
TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
TimeElapsedColumn(),
console=self.console
) as progress:
overall_task = progress.add_task(
f"[cyan]Scanning {url}...",
total=total_tests
)
for level in range(1, max_level + 1):
for risk in range(1, max_risk + 1):
test_count += 1
progress.update(
overall_task,
description=f"[cyan]Testing Level {level}, Risk {risk}..."
)
success, output = self.run_sqlmap_test(url, level, risk, techniques)
parsed = self.parse_results(output)
status = "" if success else ""
status_style = "green" if success else "red"
findings = "No vulnerabilities" if not parsed['is_vulnerable'] else f"{len(parsed['vulnerabilities'])} found!"
findings_style = "green" if not parsed['is_vulnerable'] else "bold red"
if parsed['is_vulnerable']:
self.results['vulnerabilities'].extend(parsed['vulnerabilities'])
results_table.add_row(
str(level),
str(risk),
f"[{status_style}]{status}[/{status_style}]",
f"[{findings_style}]{findings}[/{findings_style}]"
)
progress.update(overall_task, advance=1)
self.results['total_tests'] += 1
self.results['end_time'] = datetime.now()
# Display results
self.console.print()
self.console.print(results_table)
self.display_summary()
def quick_scan(self, url: str, level: int = 1, risk: int = 1):
"""Run a quick scan with default settings"""
self.results['target'] = url
self.results['start_time'] = datetime.now()
self.console.print(
Panel(
f"[cyan]Running quick scan on:[/cyan]\n[yellow]{url}[/yellow]\n[dim]Level: {level}, Risk: {risk}[/dim]",
border_style="cyan",
box=box.ROUNDED
)
)
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
TimeElapsedColumn(),
console=self.console
) as progress:
task = progress.add_task("[cyan]Scanning for vulnerabilities...", total=None)
success, output = self.run_sqlmap_test(url, level, risk)
progress.update(task, completed=True)
parsed = self.parse_results(output)
self.results['vulnerabilities'] = parsed['vulnerabilities']
self.results['total_tests'] = 1
self.results['end_time'] = datetime.now()
self.display_summary()
def display_summary(self):
"""Display a comprehensive summary of results"""
self.console.print()
# Calculate duration
duration = (self.results['end_time'] - self.results['start_time']).total_seconds()
# Create summary panel
summary_text = f"""
[cyan]Target:[/cyan] {self.results['target']}
[cyan]Total Tests:[/cyan] {self.results['total_tests']}
[cyan]Duration:[/cyan] {duration:.2f} seconds
[cyan]Vulnerabilities Found:[/cyan] {len(self.results['vulnerabilities'])}
"""
self.console.print(
Panel(
summary_text.strip(),
title="[bold]Scan Summary[/bold]",
border_style="green" if len(self.results['vulnerabilities']) == 0 else "red",
box=box.DOUBLE
)
)
# Display vulnerabilities if found
if self.results['vulnerabilities']:
self.console.print()
vuln_table = Table(title="⚠️ Vulnerabilities Detected", box=box.HEAVY)
vuln_table.add_column("Parameter", style="cyan")
vuln_table.add_column("Type", style="yellow")
vuln_table.add_column("Title", style="red")
for vuln in self.results['vulnerabilities']:
vuln_table.add_row(
vuln.get('parameter', 'N/A'),
vuln.get('type', 'N/A'),
vuln.get('title', 'N/A')
)
self.console.print(vuln_table)
self.console.print()
self.console.print(
"[bold red]⚠️ SQL injection vulnerabilities detected! Take immediate action.[/bold red]"
)
else:
self.console.print()
self.console.print(
"[bold green]✓ No SQL injection vulnerabilities detected.[/bold green]"
)
self.console.print()
def interactive_mode(self):
"""Interactive mode for user input"""
self.console.print()
self.console.print(
Panel(
"[cyan]Interactive Mode[/cyan]\n[dim]Enter target details for SQL injection testing[/dim]",
border_style="cyan"
)
)
url = Prompt.ask("\n[cyan]Enter target URL[/cyan]")
scan_type = Prompt.ask(
"[cyan]Select scan type[/cyan]",
choices=["quick", "comprehensive"],
default="quick"
)
if scan_type == "quick":
level = int(Prompt.ask("[cyan]Test level (1-5)[/cyan]", default="1"))
risk = int(Prompt.ask("[cyan]Test risk (1-3)[/cyan]", default="1"))
self.quick_scan(url, level, risk)
else:
max_level = int(Prompt.ask("[cyan]Maximum test level (1-5)[/cyan]", default="5"))
max_risk = int(Prompt.ask("[cyan]Maximum test risk (1-3)[/cyan]", default="3"))
self.comprehensive_scan(url, max_level, max_risk)
def main():
parser = argparse.ArgumentParser(
description="SQLMap CLI - Beautiful automated SQL injection testing",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
# Quick scan with default settings
python sqlmapcli.py -u "http://example.com/page?id=1"
# Comprehensive scan (all risk and level combinations)
python sqlmapcli.py -u "http://example.com/page?id=1" --comprehensive
# Custom level and risk
python sqlmapcli.py -u "http://example.com/page?id=1" --level 3 --risk 2
# Interactive mode
python sqlmapcli.py --interactive
"""
)
parser.add_argument(
'-u', '--url',
help='Target URL (e.g., "http://example.com/page?id=1")'
)
parser.add_argument(
'--comprehensive',
action='store_true',
help='Run comprehensive scan with all risk/level combinations'
)
parser.add_argument(
'--level',
type=int,
default=1,
choices=[1, 2, 3, 4, 5],
help='Level of tests to perform (1-5, default: 1)'
)
parser.add_argument(
'--risk',
type=int,
default=1,
choices=[1, 2, 3],
help='Risk of tests to perform (1-3, default: 1)'
)
parser.add_argument(
'--max-level',
type=int,
default=5,
choices=[1, 2, 3, 4, 5],
help='Maximum level for comprehensive scan (default: 5)'
)
parser.add_argument(
'--max-risk',
type=int,
default=3,
choices=[1, 2, 3],
help='Maximum risk for comprehensive scan (default: 3)'
)
parser.add_argument(
'--technique',
type=str,
default='BEUSTQ',
help='SQL injection techniques to use (default: BEUSTQ)'
)
parser.add_argument(
'-i', '--interactive',
action='store_true',
help='Run in interactive mode'
)
args = parser.parse_args()
cli = SQLMapCLI()
cli.print_banner()
# Check if sqlmap exists
if not SQLMAP_PATH.exists():
console.print(
f"[bold red]Error: sqlmap.py not found at {SQLMAP_PATH}[/bold red]",
style="bold red"
)
console.print("[yellow]Make sure you're running this script from the sqlmap directory[/yellow]")
sys.exit(1)
# Interactive mode
if args.interactive:
cli.interactive_mode()
return
# Check if URL is provided
if not args.url:
console.print("[bold red]Error: URL is required (use -u or --interactive)[/bold red]")
parser.print_help()
sys.exit(1)
# Run appropriate scan
if args.comprehensive:
cli.comprehensive_scan(
args.url,
max_level=args.max_level,
max_risk=args.max_risk,
techniques=args.technique
)
else:
cli.quick_scan(args.url, level=args.level, risk=args.risk)
if __name__ == "__main__":
main()