mirror of
https://github.com/CyberSecurityUP/NeuroSploit.git
synced 2026-02-12 14:02:45 +00:00
Add files via upload
This commit is contained in:
1627
tools/benchmark_runner.py
Normal file
1627
tools/benchmark_runner.py
Normal file
File diff suppressed because it is too large
Load Diff
1
tools/browser/__init__.py
Normal file
1
tools/browser/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Browser-based security validation tools using Playwright."""
|
||||
211
tools/browser/playwright_runner.py
Normal file
211
tools/browser/playwright_runner.py
Normal file
@@ -0,0 +1,211 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Playwright Runner - Low-level browser automation helpers for security testing.
|
||||
|
||||
Provides convenience functions for common browser-based security validation tasks.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Dict, List, Optional
|
||||
from pathlib import Path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
from playwright.async_api import async_playwright
|
||||
HAS_PLAYWRIGHT = True
|
||||
except ImportError:
|
||||
HAS_PLAYWRIGHT = False
|
||||
|
||||
|
||||
async def check_xss_reflection(url: str, payload: str, headless: bool = True) -> Dict:
|
||||
"""Check if a payload is reflected in page content or triggers a dialog.
|
||||
|
||||
Args:
|
||||
url: Target URL (payload should be in query params)
|
||||
payload: The XSS payload being tested
|
||||
headless: Run in headless mode
|
||||
|
||||
Returns:
|
||||
Dict with reflection status, dialog detection, and page content snippet
|
||||
"""
|
||||
if not HAS_PLAYWRIGHT:
|
||||
return {"error": "Playwright not installed"}
|
||||
|
||||
result = {
|
||||
"url": url,
|
||||
"payload": payload,
|
||||
"reflected": False,
|
||||
"dialog_triggered": False,
|
||||
"dialog_message": None,
|
||||
"content_snippet": ""
|
||||
}
|
||||
|
||||
async with async_playwright() as p:
|
||||
browser = await p.chromium.launch(headless=headless)
|
||||
context = await browser.new_context(ignore_https_errors=True)
|
||||
page = await context.new_page()
|
||||
|
||||
dialogs = []
|
||||
|
||||
async def on_dialog(dialog):
|
||||
dialogs.append(dialog.message)
|
||||
await dialog.dismiss()
|
||||
|
||||
page.on("dialog", on_dialog)
|
||||
|
||||
try:
|
||||
await page.goto(url, wait_until="networkidle", timeout=15000)
|
||||
content = await page.content()
|
||||
|
||||
if payload in content:
|
||||
result["reflected"] = True
|
||||
idx = content.find(payload)
|
||||
start = max(0, idx - 100)
|
||||
end = min(len(content), idx + len(payload) + 100)
|
||||
result["content_snippet"] = content[start:end]
|
||||
|
||||
if dialogs:
|
||||
result["dialog_triggered"] = True
|
||||
result["dialog_message"] = dialogs[0]
|
||||
|
||||
except Exception as e:
|
||||
result["error"] = str(e)
|
||||
finally:
|
||||
await browser.close()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
async def capture_page_state(url: str, screenshot_path: str,
|
||||
headless: bool = True) -> Dict:
|
||||
"""Capture the full state of a page: screenshot, title, headers, cookies.
|
||||
|
||||
Args:
|
||||
url: Page URL to capture
|
||||
screenshot_path: Path to save the screenshot
|
||||
headless: Run in headless mode
|
||||
|
||||
Returns:
|
||||
Dict with page title, cookies, response headers, console messages
|
||||
"""
|
||||
if not HAS_PLAYWRIGHT:
|
||||
return {"error": "Playwright not installed"}
|
||||
|
||||
result = {
|
||||
"url": url,
|
||||
"title": "",
|
||||
"screenshot": screenshot_path,
|
||||
"cookies": [],
|
||||
"console_messages": [],
|
||||
"response_headers": {},
|
||||
"status_code": None
|
||||
}
|
||||
|
||||
async with async_playwright() as p:
|
||||
browser = await p.chromium.launch(headless=headless)
|
||||
context = await browser.new_context(ignore_https_errors=True)
|
||||
page = await context.new_page()
|
||||
|
||||
console_msgs = []
|
||||
page.on("console", lambda msg: console_msgs.append({
|
||||
"type": msg.type, "text": msg.text
|
||||
}))
|
||||
|
||||
try:
|
||||
response = await page.goto(url, wait_until="networkidle", timeout=20000)
|
||||
|
||||
result["title"] = await page.title()
|
||||
result["status_code"] = response.status if response else None
|
||||
result["response_headers"] = dict(response.headers) if response else {}
|
||||
|
||||
Path(screenshot_path).parent.mkdir(parents=True, exist_ok=True)
|
||||
await page.screenshot(path=screenshot_path, full_page=True)
|
||||
|
||||
cookies = await context.cookies()
|
||||
result["cookies"] = [
|
||||
{"name": c["name"], "domain": c["domain"],
|
||||
"secure": c["secure"], "httpOnly": c["httpOnly"],
|
||||
"sameSite": c.get("sameSite", "None")}
|
||||
for c in cookies
|
||||
]
|
||||
|
||||
result["console_messages"] = console_msgs
|
||||
|
||||
except Exception as e:
|
||||
result["error"] = str(e)
|
||||
finally:
|
||||
await browser.close()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
async def test_form_submission(url: str, form_data: Dict[str, str],
|
||||
submit_selector: str = "button[type=submit]",
|
||||
screenshot_dir: str = "/tmp/form_test",
|
||||
headless: bool = True) -> Dict:
|
||||
"""Submit a form and capture before/after state.
|
||||
|
||||
Args:
|
||||
url: URL containing the form
|
||||
form_data: Dict of selector -> value to fill
|
||||
submit_selector: CSS selector for the submit button
|
||||
screenshot_dir: Directory to store screenshots
|
||||
headless: Run in headless mode
|
||||
|
||||
Returns:
|
||||
Dict with before/after screenshots, response info, and any triggered dialogs
|
||||
"""
|
||||
if not HAS_PLAYWRIGHT:
|
||||
return {"error": "Playwright not installed"}
|
||||
|
||||
ss_dir = Path(screenshot_dir)
|
||||
ss_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
result = {
|
||||
"url": url,
|
||||
"before_screenshot": str(ss_dir / "before.png"),
|
||||
"after_screenshot": str(ss_dir / "after.png"),
|
||||
"dialogs": [],
|
||||
"response_url": "",
|
||||
"status": "unknown"
|
||||
}
|
||||
|
||||
async with async_playwright() as p:
|
||||
browser = await p.chromium.launch(headless=headless)
|
||||
context = await browser.new_context(ignore_https_errors=True)
|
||||
page = await context.new_page()
|
||||
|
||||
dialogs = []
|
||||
|
||||
async def on_dialog(dialog):
|
||||
dialogs.append({"type": dialog.type, "message": dialog.message})
|
||||
await dialog.dismiss()
|
||||
|
||||
page.on("dialog", on_dialog)
|
||||
|
||||
try:
|
||||
await page.goto(url, wait_until="networkidle", timeout=15000)
|
||||
await page.screenshot(path=result["before_screenshot"])
|
||||
|
||||
# Fill form fields
|
||||
for selector, value in form_data.items():
|
||||
await page.fill(selector, value)
|
||||
|
||||
# Submit
|
||||
await page.click(submit_selector)
|
||||
await page.wait_for_load_state("networkidle")
|
||||
|
||||
await page.screenshot(path=result["after_screenshot"], full_page=True)
|
||||
result["response_url"] = page.url
|
||||
result["dialogs"] = dialogs
|
||||
result["status"] = "completed"
|
||||
|
||||
except Exception as e:
|
||||
result["error"] = str(e)
|
||||
result["status"] = "error"
|
||||
finally:
|
||||
await browser.close()
|
||||
|
||||
return result
|
||||
Reference in New Issue
Block a user