diff --git a/.github/workflows/websecscan.yml b/.github/workflows/websecscan.yml new file mode 100644 index 0000000..713ebcf --- /dev/null +++ b/.github/workflows/websecscan.yml @@ -0,0 +1,71 @@ +name: WebSecScan + +on: + schedule: + - cron: "0 3 * * *" # daily at 03:00 UTC + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: websecscan + cancel-in-progress: true + +jobs: + scan: + runs-on: ubuntu-latest + env: + VIRUSTOTAL_API_KEY: ${{ secrets.VIRUSTOTAL_API_KEY }} + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install WebSecScan + run: | + python -m pip install --upgrade pip + pip install . + + - name: Run scans + run: | + mkdir -p reports + TS=$(date -u +%Y%m%d_%H%M%S) + if [ -f targets.txt ]; then + while IFS= read -r url; do + [ -z "$url" ] && continue + websecscan "$url" --output html --fast || true + dom=$(echo "$url" | sed 's|https\?://||; s|/||g') + if [ -f "reports/scan_${dom}.html" ]; then + mv "reports/scan_${dom}.html" "reports/${TS}_${dom}.html" + fi + done < targets.txt + else + echo "No targets.txt found; skipping scans." + fi + # Disable Jekyll on GitHub Pages + touch reports/.nojekyll + + # Generate a simple index.html listing all report files + echo "WebSecScan Reports

WebSecScan Reports

Generated by GitHub Actions

To run a new scan, go to Actions and trigger the WebSecScan workflow.

" >> reports/index.html + + - name: Upload artifact (reports) + uses: actions/upload-artifact@v4 + with: + name: reports-${{ github.run_number }} + path: reports/ + + - name: Publish to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: reports + keep_files: true diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..5e91c3e --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +recursive-include scanner/templates * diff --git a/README.md b/README.md index fda9c7c..80e5f91 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,114 @@ python3 websecscan.py https://example.com --output md --active --- +## 🚀 Run on GitHub (scheduled, auto-published reports) + +Follow these steps to host the project on GitHub and keep it running on a schedule via GitHub Actions. Reports will be committed to a `gh-pages` branch and published with GitHub Pages. + +### 1) Push this project to your GitHub repo +- Create a new repository on GitHub (public or private) +- From your local machine or CI environment: +```bash +git init +git add . +git commit -m "feat: initial import of WebSecScan" +git branch -M main +git remote add origin git@github.com:/.git +git push -u origin main +``` + +### 2) Add your VirusTotal API key as a secret +- GitHub → Your repository → Settings → Secrets and variables → Actions → New repository secret +- Name: `VIRUSTOTAL_API_KEY` +- Value: your actual API key + +### 3) Add a `targets.txt` file (domains you own) +- Create a file named `targets.txt` in the repo root containing one authorized URL per line, for example: +```text +https://example.com +https://sub.example.com +``` + +### 4) Add the GitHub Actions workflow +- Create the file `.github/workflows/websecscan.yml` with the following content: +```yaml +name: WebSecScan + +on: + schedule: + - cron: "0 3 * * *" # daily at 03:00 UTC + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: websecscan + cancel-in-progress: true + +jobs: + scan: + runs-on: ubuntu-latest + env: + VIRUSTOTAL_API_KEY: ${{ secrets.VIRUSTOTAL_API_KEY }} + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install WebSecScan + run: | + python -m pip install --upgrade pip + pip install . + + - name: Run scans + run: | + mkdir -p reports + TS=$(date -u +%Y%m%d_%H%M%S) + while IFS= read -r url; do + [ -z "$url" ] && continue + websecscan "$url" --output html --fast || true + dom=$(echo "$url" | sed 's|https\?://||; s|/||g') + if [ -f "reports/scan_${dom}.html" ]; then + mv "reports/scan_${dom}.html" "reports/${TS}_${dom}.html" + fi + done < targets.txt + + - name: Upload artifact (reports) + uses: actions/upload-artifact@v4 + with: + name: reports-${{ github.run_number }} + path: reports/ + + - name: Publish to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: reports + keep_files: true +``` + +### 5) Enable GitHub Pages +- Repo → Settings → Pages → Build and deployment +- Source: `Deploy from a branch` +- Branch: `gh-pages`, Folder: `/ (root)` +- Save. Your reports will be available at `https://.github.io//` + +### 6) Run it now +- Go to Actions → `WebSecScan` → Run workflow +- After it finishes, view the Pages site or download the artifact + +### Notes and tips +- Only include domains you own or are authorized to scan in `targets.txt`. +- Remove `--fast` in the workflow to enable all checks (slower, more API use). +- To keep history, the workflow timestamps report filenames; adjust as needed. +- If you need private reports, skip GitHub Pages and rely on build artifacts only. +- For heavy scans or tighter control, consider a VPS + `cron`/`systemd` instead of Actions. + ## 🤝 Contributing Pull requests, feature suggestions, and plugins are welcome! Feel free to fork the project and submit your ideas, as I will be checking the project from time to time. @@ -118,4 +226,4 @@ Built for security researchers, red teamers, and educators. ## ⚠️ Disclaimer Use responsibly. This tool is intended for **authorized testing only**. -Do not scan websites without permission. +Do not scan websites without permission. \ No newline at end of file diff --git a/reports/scan_example.com.md b/reports/scan_example.com.md new file mode 100644 index 0000000..ea79fee --- /dev/null +++ b/reports/scan_example.com.md @@ -0,0 +1,76 @@ +# 🛡️ WebSecScan Report + +**Target:** https://example.com +**Scan Time:** 2025-10-27 18:28:40.472899 + +--- + +## 🔐 SSL Certificate + +- **issuer:** ((('countryName', 'US'),), (('organizationName', 'DigiCert Inc'),), (('commonName', 'DigiCert Global G3 TLS ECC SHA384 2020 CA1'),)) + +- **subject:** ((('countryName', 'US'),), (('stateOrProvinceName', 'California'),), (('localityName', 'Los Angeles'),), (('organizationName', 'Internet Corporation for Assigned Names and Numbers'),), (('commonName', '*.example.com'),)) + +- **valid_from:** Jan 15 00:00:00 2025 GMT + +- **valid_until:** Jan 15 23:59:59 2026 GMT + + +--- + +## 🧱 WAF Detection +**WAF:** None detected + +--- + +## 📑 Security Headers + +- **Content-Security-Policy:** Missing + +- **X-Content-Type-Options:** Missing + +- **Strict-Transport-Security:** Missing + +- **X-Frame-Options:** Missing + + +--- + +## 🧬 Tech Stack + +- None detected + + +--- + +## 📌 CVE Matches + +- None + + +--- + +## 📁 Sensitive Paths Found + +- None + + +--- + +## 📊 Risk Score +**Score:** 25/100 + +- ⚠️ Missing headers: Content-Security-Policy, X-Content-Type-Options, Strict-Transport-Security, X-Frame-Options + +- ⚠️ No WAF detected + + +--- + +## 🔗 Links Analyzed + +### https://iana.org/domains/example + +- **IP:** 192.0.43.8 +- **WHOIS:** +- **Heuristics:** diff --git a/requirements.txt b/requirements.txt index b0f63e5..cbbbf33 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,5 @@ python-whois>=0.8.0 Jinja2>=3.1.2 aiodns>=3.0.0 scikit-learn>1.3.0 -joblib>=1.3.2 \ No newline at end of file +joblib>=1.3.2 +scikit-learn \ No newline at end of file diff --git a/scanner/__pycache__/__init__.cpython-313.pyc b/scanner/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..7189496 Binary files /dev/null and b/scanner/__pycache__/__init__.cpython-313.pyc differ diff --git a/scanner/__pycache__/active_tester.cpython-313.pyc b/scanner/__pycache__/active_tester.cpython-313.pyc new file mode 100644 index 0000000..e853682 Binary files /dev/null and b/scanner/__pycache__/active_tester.cpython-313.pyc differ diff --git a/scanner/__pycache__/anti_bot.cpython-313.pyc b/scanner/__pycache__/anti_bot.cpython-313.pyc new file mode 100644 index 0000000..208dded Binary files /dev/null and b/scanner/__pycache__/anti_bot.cpython-313.pyc differ diff --git a/scanner/__pycache__/async_tools.cpython-313.pyc b/scanner/__pycache__/async_tools.cpython-313.pyc new file mode 100644 index 0000000..fd06994 Binary files /dev/null and b/scanner/__pycache__/async_tools.cpython-313.pyc differ diff --git a/scanner/__pycache__/auth_scanner.cpython-313.pyc b/scanner/__pycache__/auth_scanner.cpython-313.pyc new file mode 100644 index 0000000..abe04bc Binary files /dev/null and b/scanner/__pycache__/auth_scanner.cpython-313.pyc differ diff --git a/scanner/__pycache__/core.cpython-313.pyc b/scanner/__pycache__/core.cpython-313.pyc new file mode 100644 index 0000000..de77e57 Binary files /dev/null and b/scanner/__pycache__/core.cpython-313.pyc differ diff --git a/scanner/__pycache__/dir_brute.cpython-313.pyc b/scanner/__pycache__/dir_brute.cpython-313.pyc new file mode 100644 index 0000000..ef64984 Binary files /dev/null and b/scanner/__pycache__/dir_brute.cpython-313.pyc differ diff --git a/scanner/__pycache__/extract.cpython-313.pyc b/scanner/__pycache__/extract.cpython-313.pyc new file mode 100644 index 0000000..3bb2a5d Binary files /dev/null and b/scanner/__pycache__/extract.cpython-313.pyc differ diff --git a/scanner/__pycache__/headers.cpython-313.pyc b/scanner/__pycache__/headers.cpython-313.pyc new file mode 100644 index 0000000..074f04a Binary files /dev/null and b/scanner/__pycache__/headers.cpython-313.pyc differ diff --git a/scanner/__pycache__/heuristics.cpython-313.pyc b/scanner/__pycache__/heuristics.cpython-313.pyc new file mode 100644 index 0000000..debe8a6 Binary files /dev/null and b/scanner/__pycache__/heuristics.cpython-313.pyc differ diff --git a/scanner/__pycache__/ip_tools.cpython-313.pyc b/scanner/__pycache__/ip_tools.cpython-313.pyc new file mode 100644 index 0000000..613c1c6 Binary files /dev/null and b/scanner/__pycache__/ip_tools.cpython-313.pyc differ diff --git a/scanner/__pycache__/profiling.cpython-313.pyc b/scanner/__pycache__/profiling.cpython-313.pyc new file mode 100644 index 0000000..8d5d8b8 Binary files /dev/null and b/scanner/__pycache__/profiling.cpython-313.pyc differ diff --git a/scanner/__pycache__/recon.cpython-313.pyc b/scanner/__pycache__/recon.cpython-313.pyc new file mode 100644 index 0000000..e2b97a2 Binary files /dev/null and b/scanner/__pycache__/recon.cpython-313.pyc differ diff --git a/scanner/__pycache__/report.cpython-313.pyc b/scanner/__pycache__/report.cpython-313.pyc new file mode 100644 index 0000000..d348b92 Binary files /dev/null and b/scanner/__pycache__/report.cpython-313.pyc differ diff --git a/scanner/__pycache__/smart_detect.cpython-313.pyc b/scanner/__pycache__/smart_detect.cpython-313.pyc new file mode 100644 index 0000000..efec3a4 Binary files /dev/null and b/scanner/__pycache__/smart_detect.cpython-313.pyc differ diff --git a/scanner/__pycache__/spider.cpython-313.pyc b/scanner/__pycache__/spider.cpython-313.pyc new file mode 100644 index 0000000..d1b7b71 Binary files /dev/null and b/scanner/__pycache__/spider.cpython-313.pyc differ diff --git a/scanner/__pycache__/ssl_analyzer.cpython-313.pyc b/scanner/__pycache__/ssl_analyzer.cpython-313.pyc new file mode 100644 index 0000000..2cc65ec Binary files /dev/null and b/scanner/__pycache__/ssl_analyzer.cpython-313.pyc differ diff --git a/scanner/__pycache__/stack_fingerprint.cpython-313.pyc b/scanner/__pycache__/stack_fingerprint.cpython-313.pyc new file mode 100644 index 0000000..5fce76e Binary files /dev/null and b/scanner/__pycache__/stack_fingerprint.cpython-313.pyc differ diff --git a/scanner/__pycache__/subdomains.cpython-313.pyc b/scanner/__pycache__/subdomains.cpython-313.pyc new file mode 100644 index 0000000..22dd65b Binary files /dev/null and b/scanner/__pycache__/subdomains.cpython-313.pyc differ diff --git a/scanner/__pycache__/virustotal.cpython-313.pyc b/scanner/__pycache__/virustotal.cpython-313.pyc new file mode 100644 index 0000000..4b341b5 Binary files /dev/null and b/scanner/__pycache__/virustotal.cpython-313.pyc differ diff --git a/scanner/__pycache__/vuln_check.cpython-313.pyc b/scanner/__pycache__/vuln_check.cpython-313.pyc new file mode 100644 index 0000000..b46fcee Binary files /dev/null and b/scanner/__pycache__/vuln_check.cpython-313.pyc differ diff --git a/scanner/async_tools.py b/scanner/async_tools.py index dd191b3..1dac8ce 100644 --- a/scanner/async_tools.py +++ b/scanner/async_tools.py @@ -52,7 +52,7 @@ def load_plugins(plugin_folder="plugins"): spec.loader.exec_module(mod) if hasattr(mod, "run_plugin"): plugins.append(mod) - return plugins + return plugins def run_plugins(plugins, url, html, headers): results = [] diff --git a/scanner/core.py b/scanner/core.py index 1b5034e..10acb75 100644 --- a/scanner/core.py +++ b/scanner/core.py @@ -140,9 +140,9 @@ def scan_website(url, fast_mode=False, use_plugins=False, output_format="json", soup = BeautifulSoup(resp.text, 'html.parser') for script in soup.find_all('script'): if script.string: - js_snippets.appeend(script.string) + js_snippets.append(script.string) report["suspicious_analysis"] = is_url_suspicious(link, js_snippets) - except: + except Exception: report["suspicious_analysis"] = {"error": "Failed to analyze scripts"} @@ -157,10 +157,12 @@ def scan_website(url, fast_mode=False, use_plugins=False, output_format="json", report["ip"] = ip report["host_profile"] = get_host_profile(ip) - except: + except Exception: report["ip"] = None report["host_profile"] = {"error": "Could not resolve IP"} - scan_summary["reports"].append(report) + + # Always record the report for this link + scan_summary["reports"].append(report) # Final risk score scan_summary["risk"] = calculate_risk_score(scan_summary) diff --git a/scanner/extract.py b/scanner/extract.py index 68dfb28..abb2ea8 100644 --- a/scanner/extract.py +++ b/scanner/extract.py @@ -16,5 +16,5 @@ def extract_links(url): def detect_ip_grabber(url): import re patterns = [r'\d{10,}', r'[a-zA-Z]{20,}', r'[0-9a-f]{32}'] - domains = ["grabify.link", "iplogger.org", "ipgrabber.io", "grabify.link"] + domains = ["grabify.link", "iplogger.org", "ipgrabber.io"] return any(re.search(p, url) for p in patterns) or any(d in url for d in domains) diff --git a/scanner/headers.py b/scanner/headers.py index f01aab3..ad9a3e7 100644 --- a/scanner/headers.py +++ b/scanner/headers.py @@ -8,5 +8,5 @@ def analyze_headers(headers): return {h: headers.get(h, "Missing") for h in important} def detect_waf(headers): - waf_keys = ["Server", "X-CDN", "CF-RAY", "X-Sucuro-ID", "X-Akamai"] + waf_keys = ["Server", "X-CDN", "CF-RAY", "X-Sucuri-ID", "X-Akamai"] return {k: headers[k] for k in waf_keys if k in headers} diff --git a/scanner/profiling.py b/scanner/profiling.py index 0f3dc9f..f884378 100644 --- a/scanner/profiling.py +++ b/scanner/profiling.py @@ -99,7 +99,7 @@ def calculate_risk_score(scan_summary): if missing: penalties.append(f"Missing headers: {', '.join(missing)}") - if scan_summary.get("waf") in ["None", "", None]: + if not scan_summary.get("waf"): score += 5 penalties.append("No WAF detected") @@ -120,5 +120,4 @@ def calculate_risk_score(scan_summary): risk_score = min(score, 100) - return {"risk_score": risk_score, "penalties": penalties} - + return {"risk_score": risk_score, "penalties": penalties} \ No newline at end of file diff --git a/scanner/report.py b/scanner/report.py index b24d291..fbe8238 100644 --- a/scanner/report.py +++ b/scanner/report.py @@ -1,27 +1,35 @@ import os import json from jinja2 import Environment, FileSystemLoader +from pathlib import Path -template_loader = FileSystemLoader('./templates') -env = Environment(loader=template_loader) - -# Setup Jinja2 environment -template_loader = FileSystemLoader("./templates") +# Setup Jinja2 environment once, resolving templates in-package +PACKAGE_DIR = Path(__file__).resolve().parent +DEFAULT_TEMPLATE_DIR = PACKAGE_DIR / "templates" +template_loader = FileSystemLoader(str(DEFAULT_TEMPLATE_DIR)) env = Environment(loader=template_loader) def export_html_report(scan_data, output_path): try: + # Ensure output directory exists + output_dir = os.path.dirname(output_path) or "." + os.makedirs(output_dir, exist_ok=True) + template = env.get_template("report_template.html") rendered = template.render(scan=scan_data) with open(output_path, "w", encoding="utf-8") as f: f.write(rendered) return True except Exception as e: - return f"HTML export failded: {e}" + return f"HTML export failed: {e}" def export_md_report(scan_data, output_path): try: + # Ensure output directory exists + output_dir = os.path.dirname(output_path) or "." + os.makedirs(output_dir, exist_ok=True) + template = env.get_template("report_template.md") rendered = template.render(scan=scan_data) with open(output_path, "w", encoding="utf-8") as f: @@ -31,7 +39,12 @@ def export_md_report(scan_data, output_path): return f"Markdown export failed: {e}" def save_scan_report(data, filename): - os.makedirs("reports", exist_ok=True) - with open(os.path.join("reports", filename), "w") as f: + """Save JSON report to the provided path. + + If 'filename' includes directories, they will be created automatically. + """ + output_dir = os.path.dirname(filename) or "." + os.makedirs(output_dir, exist_ok=True) + with open(filename, "w", encoding="utf-8") as f: json.dump(data, f, indent=2) - print(f"✅ Saved to reports/{filename}") \ No newline at end of file + print(f"✅ Saved to {filename}") \ No newline at end of file diff --git a/templates/report_template.html b/scanner/templates/report_template.html similarity index 73% rename from templates/report_template.html rename to scanner/templates/report_template.html index 9f6b5eb..5e7eac9 100644 --- a/templates/report_template.html +++ b/scanner/templates/report_template.html @@ -37,23 +37,35 @@

📑 Security Headers

🧬 Technology Stack

    - {% for tech in scan.tech_stack %} -
  • {{ tech }}
  • - {% endfor %} + {% if scan.tech_stack is defined and scan.tech_stack %} + {% for tech in scan.tech_stack %} +
  • {{ tech }}
  • + {% endfor %} + {% else %} +
  • None detected
  • + {% endif %}

📌 CVE Matches

    - {% for k, v in scan.cve_matches.items() %} -
  • {{ k }}: {{ v | join(", ") }}
  • - {% endfor %} + {% if scan.cve_matches is defined and scan.cve_matches %} + {% for k, v in scan.cve_matches.items() %} +
  • {{ k }}: {{ v | join(", ") }}
  • + {% endfor %} + {% else %} +
  • None
  • + {% endif %}

📁 Sensitive Paths

    - {% for path in scan.dir_brute %} -
  • {{ path }}
  • - {% endfor %} + {% if scan.dir_brute is defined and scan.dir_brute %} + {% for path in scan.dir_brute %} +
  • {{ path }}
  • + {% endfor %} + {% else %} +
  • None
  • + {% endif %}

📊 Risk Score

@@ -77,4 +89,4 @@

🔗 Links Analyzed

{% endfor %} - + \ No newline at end of file diff --git a/templates/report_template.md b/scanner/templates/report_template.md similarity index 78% rename from templates/report_template.md rename to scanner/templates/report_template.md index a3ef0fd..78c59dd 100644 --- a/templates/report_template.md +++ b/scanner/templates/report_template.md @@ -25,23 +25,35 @@ --- ## 🧬 Tech Stack +{% if scan.tech_stack is defined and scan.tech_stack %} {% for tech in scan.tech_stack %} - {{ tech }} {% endfor %} +{% else %} +- None detected +{% endif %} --- ## 📌 CVE Matches +{% if scan.cve_matches is defined and scan.cve_matches %} {% for k, v in scan.cve_matches.items() %} - **{{ k }}:** {{ v | join(", ") }} {% endfor %} +{% else %} +- None +{% endif %} --- ## 📁 Sensitive Paths Found +{% if scan.dir_brute is defined and scan.dir_brute %} {% for path in scan.dir_brute %} - `{{ path }}` {% endfor %} +{% else %} +- None +{% endif %} --- @@ -62,4 +74,4 @@ - **IP:** {{ r.ip }} - **WHOIS:** {{ r.whois }} - **Heuristics:** {{ r.heuristics }} -{% endfor %} +{% endfor %} \ No newline at end of file diff --git a/setup.py b/setup.py index b582985..0091c31 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,8 @@ setup( name="websecscan", version="1.0.0", - author="Your Name", + author="Arli", + author_email='arliturka2@gmail.com', description="Advanced Website Security Scanner", packages=find_packages(), include_package_data=True, @@ -18,13 +19,16 @@ ], entry_points={ 'console_scripts': [ - 'websecscan = websecscan:main' + 'websecscan = scanner.core:main' ] }, + package_data={ + "scanner": ["templates/*.html", "templates/*.md"], + }, classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent" ], - python_requires='>=3.7', + python_requires='>=3.9', ) diff --git a/targets.txt b/targets.txt new file mode 100644 index 0000000..46cafae --- /dev/null +++ b/targets.txt @@ -0,0 +1,3 @@ +https://youtube.com +https://facepunch.com +https://riotgames.com diff --git a/websecscan.egg-info/PKG-INFO b/websecscan.egg-info/PKG-INFO new file mode 100644 index 0000000..c666dc7 --- /dev/null +++ b/websecscan.egg-info/PKG-INFO @@ -0,0 +1,19 @@ +Metadata-Version: 2.4 +Name: websecscan +Version: 1.0.0 +Summary: Advanced Website Security Scanner +Classifier: Programming Language :: Python :: 3 +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Requires-Python: >=3.9 +Requires-Dist: requests +Requires-Dist: aiohttp +Requires-Dist: beautifulsoup4 +Requires-Dist: dnspython +Requires-Dist: python-whois +Requires-Dist: rich +Requires-Dist: Jinja2 +Dynamic: classifier +Dynamic: requires-dist +Dynamic: requires-python +Dynamic: summary diff --git a/websecscan.egg-info/SOURCES.txt b/websecscan.egg-info/SOURCES.txt new file mode 100644 index 0000000..12dc3ca --- /dev/null +++ b/websecscan.egg-info/SOURCES.txt @@ -0,0 +1,32 @@ +MANIFEST.in +README.md +setup.py +scanner/__init__.py +scanner/active_tester.py +scanner/anti_bot.py +scanner/async_tools.py +scanner/auth_scanner.py +scanner/core.py +scanner/dir_brute.py +scanner/extract.py +scanner/headers.py +scanner/heuristics.py +scanner/ip_tools.py +scanner/profiling.py +scanner/recon.py +scanner/report.py +scanner/smart_detect.py +scanner/spider.py +scanner/ssl_analyzer.py +scanner/stack_fingerprint.py +scanner/subdomains.py +scanner/virustotal.py +scanner/vuln_check.py +scanner/templates/report_template.html +scanner/templates/report_template.md +websecscan.egg-info/PKG-INFO +websecscan.egg-info/SOURCES.txt +websecscan.egg-info/dependency_links.txt +websecscan.egg-info/entry_points.txt +websecscan.egg-info/requires.txt +websecscan.egg-info/top_level.txt \ No newline at end of file diff --git a/websecscan.egg-info/dependency_links.txt b/websecscan.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/websecscan.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/websecscan.egg-info/entry_points.txt b/websecscan.egg-info/entry_points.txt new file mode 100644 index 0000000..e463b40 --- /dev/null +++ b/websecscan.egg-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +websecscan = scanner.core:main diff --git a/websecscan.egg-info/requires.txt b/websecscan.egg-info/requires.txt new file mode 100644 index 0000000..6944864 --- /dev/null +++ b/websecscan.egg-info/requires.txt @@ -0,0 +1,7 @@ +requests +aiohttp +beautifulsoup4 +dnspython +python-whois +rich +Jinja2 diff --git a/websecscan.egg-info/top_level.txt b/websecscan.egg-info/top_level.txt new file mode 100644 index 0000000..421ce58 --- /dev/null +++ b/websecscan.egg-info/top_level.txt @@ -0,0 +1 @@ +scanner