Skip to content

Commit 7f5df82

Browse files
authored
Add files via upload
1 parent 458a28a commit 7f5df82

100 files changed

Lines changed: 1647 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

requirements.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
httpx
2+
PySide6
3+
aiofiles
4+
rich
5+
typer
6+
colorama
7+
jinja2
8+
reportlab

upload_forge.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import sys
2+
import os
3+
4+
# Ensure the package is in python path
5+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
6+
7+
from upload_forge.cli.cli_interface import app
8+
9+
def main():
10+
app()
11+
12+
if __name__ == "__main__":
13+
main()
6.01 KB
Binary file not shown.

upload_forge/cli/cli_interface.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import typer
2+
import asyncio
3+
from typing import Optional
4+
from rich.console import Console
5+
from rich.table import Table
6+
from rich.panel import Panel
7+
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn
8+
from rich import box
9+
from ..core.scanner import Scanner
10+
from ..reporting.json_report import generate_json_report
11+
from ..reporting.html_report import generate_html_report
12+
13+
app = typer.Typer(help="UploadForge - Professional File Upload Vulnerability Scanner")
14+
console = Console()
15+
16+
BANNER = """
17+
[bold green]
18+
█ ██ ██▓███ ██▓ ▒█████ ▄▄▄ ▓█████▄ █████▒▒█████ ██▀███ ▄████ ▓█████
19+
██ ▓██▒▓██░ ██▒▓██▒ ▒██▒ ██▒▒████▄ ▒██▀ ██▌ ▓██ ▒▒██▒ ██▒▓██ ▒ ██▒ ██▒ ▀█▒▓█ ▀
20+
▓██ ▒██░▓██░ ██▓▒▒██░ ▒██░ ██▒▒██ ▀█▄ ░██ █▌ ▒████ ░▒██░ ██▒▓██ ░▄█ ▒▒██░▄▄▄░▒███
21+
▓▓█ ░██░▒██▄█▓▒ ▒▒██░ ▒██ ██░░██▄▄▄▄██ ░▓█▄ ▌ ░▓█▒ ░▒██ ██░▒██▀▀█▄ ░▓█ ██▓▒▓█ ▄
22+
▒▒█████▓ ▒██▒ ░ ░░██████▒░ ████▓▒░ ▓█ ▓██▒░▒████▓ ░▒█░ ░ ████▓▒░░██▓ ▒██▒░▒▓███▀▒░▒████▒
23+
░▒▓▒ ▒ ▒ ▒▓▒░ ░ ░░ ▒░▓ ░░ ▒░▒░▒░ ▒▒ ▓▒█░ ▒▒▓ ▒ ▒ ░ ░ ▒░▒░▒░ ░ ▒▓ ░▒▓░ ░▒ ▒ ░░ ▒░ ░
24+
░░▒░ ░ ░ ░▒ ░ ░ ░ ▒ ░ ░ ▒ ▒░ ▒ ▒▒ ░ ░ ▒ ▒ ░ ░ ▒ ▒░ ░▒ ░ ▒░ ░ ░ ░ ░ ░
25+
░░░ ░ ░ ░░ ░ ░ ░ ░ ░ ▒ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ░ ▒ ░░ ░ ░ ░ ░ ░
26+
░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
27+
28+
[/bold green]
29+
[bold white]Professional File Upload Vulnerability Scanner[/bold white]
30+
"""
31+
32+
@app.command()
33+
def scan(
34+
url: str = typer.Option(..., "--url", "-u", help="Target URL for file upload"),
35+
param: str = typer.Option("file", "--param", "-p", help="POST parameter name for the file"),
36+
upload_dir: str = typer.Option(None, "--upload-dir", "-d", help="Directory where files are uploaded (URL path)"),
37+
output: str = typer.Option("report.json", "--output", "-o", help="Output report file (json or html)"),
38+
proxy: str = typer.Option(None, "--proxy", help="Proxy URL (e.g., http://127.0.0.1:8080)"),
39+
cookie: str = typer.Option(None, "--cookie", help="Cookie string"),
40+
header: str = typer.Option(None, "--header", help="Header string (Key:Value)")
41+
):
42+
"""
43+
Start a scan against a target.
44+
"""
45+
console.print(BANNER)
46+
47+
panel = Panel(f"Target: [bold cyan]{url}[/bold cyan]\nParam: [bold cyan]{param}[/bold cyan]\nOutput: [bold cyan]{output}[/bold cyan]",
48+
title="[bold yellow]Scan Configuration[/bold yellow]", border_style="green", box=box.ROUNDED)
49+
console.print(panel)
50+
51+
proxies = None
52+
if proxy:
53+
proxies = {"http://": proxy, "https://": proxy}
54+
55+
headers = {}
56+
if header:
57+
try:
58+
key, val = header.split(":", 1)
59+
headers[key.strip()] = val.strip()
60+
except:
61+
console.print("[red]Invalid header format[/red]")
62+
63+
if cookie:
64+
headers["Cookie"] = cookie
65+
66+
scanner = Scanner()
67+
68+
# Run async scan in sync context
69+
loop = asyncio.get_event_loop()
70+
if loop.is_closed():
71+
loop = asyncio.new_event_loop()
72+
asyncio.set_event_loop(loop)
73+
74+
# Wrapper to show progress
75+
async def run_scan_with_progress():
76+
with Progress(
77+
SpinnerColumn(),
78+
TextColumn("[progress.description]{task.description}"),
79+
BarColumn(),
80+
console=console
81+
) as progress:
82+
task = progress.add_task("[cyan]Scanning...", total=None)
83+
84+
# Monkey patch the scanner to update progress?
85+
# Or just run it. The scanner runs sequentially in current impl.
86+
# Ideally we refactor scanner to report progress.
87+
# For now, we just show an indeterminate spinner.
88+
result = await scanner.scan(
89+
target_url=url,
90+
file_param=param,
91+
upload_dir=upload_dir,
92+
proxies=proxies,
93+
headers=headers
94+
)
95+
progress.update(task, completed=100)
96+
return result
97+
98+
result = loop.run_until_complete(run_scan_with_progress())
99+
100+
console.print("\n[bold]Scan completed![/bold]")
101+
102+
stats_table = Table(title="Scan Statistics", box=box.ROUNDED)
103+
stats_table.add_column("Metric", style="cyan")
104+
stats_table.add_column("Value", style="magenta")
105+
stats_table.add_row("Total Requests", str(result.stats['total_requests']))
106+
stats_table.add_row("Vulnerabilities Found", str(result.stats['vulns_found']))
107+
stats_table.add_row("Time Taken", str(result.end_time - result.start_time))
108+
console.print(stats_table)
109+
110+
if result.findings:
111+
findings_table = Table(title="Vulnerabilities Detected", box=box.ROUNDED, show_lines=True)
112+
findings_table.add_column("Risk", style="bold red")
113+
findings_table.add_column("Name", style="yellow")
114+
findings_table.add_column("Payload", style="green")
115+
findings_table.add_column("Proof", style="white")
116+
117+
for finding in result.findings:
118+
risk_style = "red" if finding.risk_level in ["Critical", "High"] else "yellow"
119+
findings_table.add_row(
120+
f"[{risk_style}]{finding.risk_level}[/{risk_style}]",
121+
finding.name,
122+
finding.payload,
123+
finding.proof[:50] + "..."
124+
)
125+
console.print(findings_table)
126+
else:
127+
console.print(Panel("[green]No vulnerabilities found. Target seems secure against these payloads.[/green]", border_style="green"))
128+
129+
if output.endswith(".html"):
130+
generate_html_report(result, output)
131+
else:
132+
generate_json_report(result, output)
133+
134+
console.print(f"[bold green]Report saved to {output}[/bold green]")
135+
136+
@app.command()
137+
def gui():
138+
"""
139+
Launch the Graphical User Interface.
140+
"""
141+
from ..gui.main_window import run_gui
142+
run_gui()
143+
144+
if __name__ == "__main__":
145+
app()
3.95 KB
Binary file not shown.
3.48 KB
Binary file not shown.
1.79 KB
Binary file not shown.
2.12 KB
Binary file not shown.
3.25 KB
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)