Giter Site home page Giter Site logo

byt3bl33d3r / witnessme Goto Github PK

View Code? Open in Web Editor NEW
711.0 22.0 109.0 360 KB

Web Inventory tool, takes screenshots of webpages using Pyppeteer (headless Chrome/Chromium) and provides some extra bells & whistles to make life easier.

License: GNU General Public License v3.0

Python 91.47% Dockerfile 0.81% Makefile 0.74% HTML 6.98%
security-tools web-inventory screenshots osint python3 chromium reconnaissance security headless-chrome

witnessme's Introduction

WitnessMe

WitnessMe

WitnessMe is primarily a Web Inventory tool inspired by Eyewitness, its also written to be extensible allowing you to create custom functionality that can take advantage of the headless browser it drives in the back-end.

WitnessMe uses the Pyppeteer library to drive Headless Chromium.

Table of Contents

Motivation

Are there are a bunch of other tools that do this? Absolutely. See the following projects for alternatives (I'm sure there are more, these are the ones I've personally tried):

The reason why I wrote WitnessMe was that none of these projects had all of the features I wanted/needed in order for them to work well within my workflow. Additionally, some of them are prone to a decent amount of installation/dependency hell.

Here are some of the main features that make WitnessMe "stand out":

  • Written in Python 3.7+
  • Ability to parse extremely large Nessus and NMap XML files
  • Docker compatible
  • No installation/dependency hell
  • Full test suite! Everything is less prone to bugs
  • CSV & HTML reporting
  • HTTP Proxy Support
  • Provides a RESTful API! Scan stuff remotely!
  • CLI interface to view and search scan results without having to view the reports.
  • Signature scanning (Signatures use YAML files)
  • Preview screenshots directly in the terminal (On MacOSX/ITerm2 and some Nix terminals)
  • Extensibly written, allowing you to add functionality that can take advantage of headless chromium.
  • Built to be deployed to the Clouds (e.g. GCP Cloud Run , AWS ElasticBeanstalk etc...)

Installation

Docker

Running WitnessMe from a Docker container is fully supported and is the easiest/recommended way of using the tool.

Note: it is highly recommended to give the Docker container at least 4GB of RAM during large scans as Chromium can be a resource hog. If you keep running into "Page Crash" errors, it's because your container does not have enough memory. On Mac/Windows you can change this by clicking the Docker Task Bar Icon -> Preferences -> Resources. For Linux, refer to Docker's documentation

Pull the image from Docker Hub:

docker pull byt3bl33d3r/witnessme

You can then spin up a docker container, run it like the main witnessme script and pass it the same arguments:

docker run --rm -ti $IMAGE_ID screenshot https://google.com 192.168.0.1/24

Alternatively, you can drop into a shell within the container and run the tools that way. This also allows you to execute the wmdb and wmapi scripts.

docker run --rm -ti --entrypoint=/bin/sh $IMAGE_ID

Python Package

WitnessMe is also available as a Python package (Python 3.7 or above is required). If you do install it this way it is extremely recommended to use pipx as it takes care of installing everything in isolated environments for you in a seamless manner.

Run the following commands:

python3 -m pip install --user pipx
pipx install witnessme

All of the WitnessMe scripts should now be in your PATH and ready to go.

Development Install

You really should only install WitnessMe this way if you intend to hack on the source code. You're going to Python 3.7+ and Poetry: please refer to the Poetry installation documentation in order to install it.

git clone https://github.com/byt3bl33d3r/WitnessMe && cd WitnessMe
poetry install

Quick Starts

Finding F5 Load Balancers Vulnerable to CVE-2020-5902

Install WitnessMe using Docker:

docker pull byt3bl33d3r/witnessme

Get the $IMAGE_ID from the docker images command output, then run the following command to drop into a shell inside the container. Additionally, specify the -v flag to mount the current directory inside the container at the path /transfer in order to copy the scan results back to your host machine (if so desired):

docker run -it --entrypoint=/bin/sh -v $(pwd):/transfer $IMAGE_ID

Scan your network using WitnessMe, it can accept multiple .Nessus files, Nmap XMLs, IP ranges/CIDRs. Example:

witnessme screenshot 10.0.1.0/24 192.168.0.1-20 ~/my_nessus_scan.nessus ~/my_nmap_scan.xml

After the scan is finished, a folder will have been created in the current directory with the results. Access the results using the wmdb command line utility:

wmdb scan_2020_$TIME/

To quickly identify F5 load balancers, first perform a signature scan using the scan command. Then search for "BIG-IP" or "F5" using the servers command (this will search for the "BIG-IP" and "F5" string in the signature name, page title and server header):

image

Additionally, you can generate an HTML or CSV report using the following commands:

WMDB ≫ generate_report html
WMDB ≫ generate_report csv

You can then copy the entire scan folder which will contain all of the reports and results to your host machine by copying it to the /transfer folder.

Scraping Javascript Heavy Webpages

As of v1.5.0, WitnessMe has a grab command which allows you to quickly scrape Javascript heavy webpages by rendering the page first with Headless Chromium and then parsing the resulting HTML using the specified XPath (see here for an XPath cheatsheet).

Below are a few examples to get your started.

This grabs a list of all advertised domains on the 144.161.160.0/23 subnet from Hurricane Electric's BGP Toolkit:

witnessme -d grab -x '//div[@id="dns"]/table//tr/td[2]/a/text()' https://bgp.he.net/net/144.161.160.0/23#_dns

RESTful API

As of version 1.0, WitnessMe has a RESTful API which allows you to interact with the tool remotely.

Note: Currently, the API does not implement any authentication mechanisms. Make sure to allow/deny access at the transport level

To start the RESTful API for testing/development purposes run :

wmapi

The API documentation will then be available at http://127.0.0.1:8000/docs

Uvicorn should be used to enable SSL and run the API in production. See this dockerfile for an example.

Deploying to the Cloud (™)

Since WitnessMe has a RESTful API now, you can deploy it to the magical cloud and perform scanning from there. This would have a number of benefits, including giving you a fresh external IP on every scan (More OPSEC safe when assessing attack surface on Red Teams).

There are a number of ways of doing this, you can obviously do it the traditional way (e.g. spin up a machine, install docker etc..).

Recently cloud service providers started offering ways of running Docker containers directly in a fully managed environment. Think of it as serverless functions (e.g. AWS Lambdas) only with Docker containers.

This would technically allow you to really quickly deploy and run WitnessMe (or really anything in a Docker container) without having to worry about underlying infrastructure and removes a lot of the security concerns that come with that.

Below are some of the ones I've tried along with the steps necessary to get it going and any issues I encountered.

GCP Cloud Run

Unfortunately, it seems like Cloud Run doesn't allow outbound internet access to containers, if anybody knows of a way to get around this please get in touch

Cloud Run is by far the easiest of these services to work with.

This repository includes the cloudbuild.yaml file necessary to get this setup and running.

From the repositories root folder (after you authenticated and setup a project), these two commands will automatically build the Docker image, publish it to the Gcloud Container Registry and deploy a working container to Cloud Run:

gcloud builds submit --config cloudbuild.yaml
gcloud run deploy --image gcr.io/$PROJECT_ID/witnessme --platform managed

The output will give you a HTTPS url to invoke the WitnessMe RESTful API from :)

When you're done:

gcloud run services delete witnessme
gcloud container images delete gcr.io/$PROJECT_ID/witnessme

AWS ElasticBeanstalk

TO DO

Usage

There are 3 main utilities:

  • witnessme: is the main CLI interface.
  • wmdb: allows you to browse the database (created on each scan) to view results and generate reports.
  • wmapi: provides a RESTful API to schedule, start, stop and monitor scans.

Modes of Operations

As of v1.5.0 there are two main modes (commands) that the witnessme utility Supports:

  • The screenshot command, you guessed it, screenshots webpages. This is the main functionality.
  • The grab command allows you to scrape pages and quickly grab server headers.
usage: witnessme [-h] [--threads THREADS] [--timeout TIMEOUT] [-d] [-v] {screenshot,grab} ...

WitnessMe!

positional arguments:
  {screenshot,grab}

optional arguments:
  -h, --help         show this help message and exit
  --threads THREADS  Number of concurrent browser tab(s) to open
                     [WARNING: This can cause huge RAM consumption if set to high values] (default: 15)
  --timeout TIMEOUT  Timeout for each connection attempt in seconds (default: 15)
  -d, --debug        Enable debug output (default: False)
  -v, --version      show program's version number and exit

Screenshot Mode

$ witnessme screenshot --help
usage: witnessme screenshot [-h] [-p PORTS [PORTS ...]] target [target ...]

positional arguments:
  target                The target IP(s), range(s), CIDR(s) or hostname(s), NMap XML file(s), .Nessus file(s)

optional arguments:
  -h, --help            show this help message and exit
  -p PORTS [PORTS ...], --ports PORTS [PORTS ...]
                        Ports to scan if IP Range/CIDR is provided

Can accept a mix of .Nessus file(s), Nmap XML file(s), files containing URLs and/or IPs, IP addresses/ranges/CIDRs and URLs or alternatively read from stdin.

Note: WitnessMe detects .Nessus and NMap files by their extension so make sure Nessus files have a .nessus extension and NMap scans have a .xml extension

Long story short, should be able to handle anything you throw at it:

witnessme screenshot 192.168.1.0/24 192.168.1.10-20 https://bing.com ~/my_nessus_scan.nessus ~/my_nmap_scan.xml ~/myfilewithURLSandIPs
$ cat my_domain_list.txt | witnessme screenshot -

If an IP address/range/CIDR is specified as a target, WitnessMe will attempt to screenshot HTTP & HTTPS pages on ports 80, 8080, 443, 8443 by default. This is customizable with the --port argument.

Once a scan is completed, a folder with all the screenshots and a database will be in the current directory, point wmdb to the folder in order to see the results.

wmdb scan_2019_11_05_021237/

Grab Mode

$ witnessme grab --help
usage: witnessme grab [-h] [-x XPATH | -l] target [target ...]

positional arguments:
  target                The target IP(s), range(s), CIDR(s) or hostname(s), NMap XML file(s), .Nessus file(s)

optional arguments:
  -h, --help            show this help message and exit
  -x XPATH, --xpath XPATH
                        XPath to use
  -l, --links           Get all links

The grab subcommand allows you to render Javascript heavy webpages and scrape their content using XPaths. See this section for some examples.

Interacting with the Scan Database

Once a scan is completed (using the screenshot mode), a folder with all the screenshots and a database will be in the current directory, point wmdb to the folder in order to see the results.

wmdb scan_2019_11_05_021237/

This will drop you into the WMDB CLI menu.

Pressing tab will show you the available commands and a help menu:

Tab

The servers and hosts commands in the wmdb CLI accept 1 argument. WMCLI is smart enough to know what you're trying to do with that argument

Server Command

No arguments will show all discovered servers. Passing it an argument will search the title and server columns for that pattern (it's case insensitive).

For example if you wanted to search for all discovered Apache Tomcat servers:

  • servers tomcat or servers 'apache tomcat'

Similarly if you wanted to find servers with a 'login' in the title:

  • servers login

Hosts Command

No arguments will show all discovered hosts. Passing it an argument will search the IP and Hostname columns for that pattern (it's case insensitive). If the value corresponds to a Host ID it will show you the host information and all of the servers discovered on that host which is extremely useful for reporting purposes and/or when targeting specific hosts.

Signature Scan

You can perform a signature scan on all discovered services using the scan command.

Generating Reports

You can use the generate_report command in the wmdb cli to generate reports in HTML or CSV format. To generate a HTML report simply run generate_report without any arguments. Here's an example of what it'll look like:

image

To generate a CSV report:

WMDB ≫ generate_report csv

The reports will then be available in the scan folder.

Proxying

As of v1.5 WitnessMe supports proxying all of its traffic through an HTTP proxy. Specify a HTTP_PROXY environment variable to force the underlying headless browser to proxy its traffic through the desired host:

HTTP_PROXY=http://127.0.0.1:8080 witnessme screenshot ~/my_targets.txt
HTTP_PROXY=http://127.0.0.1:8080 witnessme grab https://www.google.com

Preview Screenshots Directly in the Terminal

Note: this feature will only work if you're on MacOSX and using ITerm2

You can preview screenshots directly in the terminal using the show command:

ScreenPreview

Writing Signatures

If you run into a new webapp write a signature for it! It's beyond simple and they're all in YAML!

Don't believe me? Here's the AirOS signature (you can find them all in the signatures directory):

credentials:
- password: ubnt
  username: ubnt
name: AirOS
signatures:
- airos_logo.png
- form enctype="multipart/form-data" id="loginform" method="post"
- align="center" class="loginsubtable"
- function onLangChange()
# AirOS ubnt/ubnt

Yup that's it. Just plop it in the signatures folder and POW! Done.

witnessme's People

Contributors

byt3bl33d3r avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

witnessme's Issues

TypeError when parsing nmap file

The following error is thrown when an nmap XML is given as input :

  File "/home/neo/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/witnessme/parsers.py", line 109, in parser_callback
    if port["@protocol"] == "tcp" and port["state"]["@state"] == "open":
TypeError: string indices must be integers

Unable to run witnessme screenshot command.

Hi, when i want to run any command like witnessme screenshot http://192.168.1.1:80, i get error:
google chrome and other dependencies was installed, but maybe i lose something!

─# witnessme screenshot http://192.168.1.1:80
[witnessme.screenshot] INFO - Starting scan 62441da4-2381-4480-a817-64ba2901780a
[witnessme.headlessbrowser] INFO - Starting headless browser
[witnessme.headlessbrowser] WARNING - Running under root privileges, browser will start with --no-sandbox
Traceback (most recent call last):
  File "/usr/bin/witnessme", line 33, in <module>
    sys.exit(load_entry_point('witnessme==1.5.0', 'console_scripts', 'witnessme')())
  File "/usr/lib/python3/dist-packages/witnessme/console/witnessme.py", line 113, in run
    args.func(args)
  File "/usr/lib/python3/dist-packages/witnessme/utils.py", line 41, in wrapper
    return asyncio.run(f(*args, **kwargs))
  File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/usr/lib/python3/dist-packages/witnessme/console/witnessme.py", line 19, in screenshot
    await cmd.start()
  File "/usr/lib/python3/dist-packages/witnessme/commands/screenshot.py", line 128, in start
    await self._scan_task
  File "/usr/lib/python3/dist-packages/witnessme/commands/screenshot.py", line 122, in setup_and_run
    await self._browser.run(self.target, self.ports)
  File "/usr/lib/python3/dist-packages/witnessme/headlessbrowser.py", line 163, in run
    await asyncio.wait_for(
  File "/usr/lib/python3.9/asyncio/tasks.py", line 479, in wait_for
    return fut.result()
  File "/usr/lib/python3/dist-packages/witnessme/headlessbrowser.py", line 114, in start_browser
    browser = await pyppeteer.launch(
  File "/usr/lib/python3/dist-packages/pyppeteer/launcher.py", line 306, in launch
    return await Launcher(options, **kwargs).launch()
  File "/usr/lib/python3/dist-packages/pyppeteer/launcher.py", line 169, in launch
    self.connection = Connection(self.browserWSEndpoint, self._loop, connectionDelay, )
  File "/usr/lib/python3/dist-packages/pyppeteer/connection.py", line 43, in __init__
    self._ws = websockets.client.connect(
  File "/usr/lib/python3/dist-packages/websockets/imports.py", line 96, in __getattr__
    raise AttributeError(f"module {package!r} has no attribute {name!r}")
AttributeError: module 'websockets' has no attribute 'client'
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/pyppeteer/launcher.py", line 152, in _close_process
    self._loop.run_until_complete(self.killChrome())
  File "/usr/lib/python3.9/asyncio/base_events.py", line 617, in run_until_complete
    self._check_closed()
  File "/usr/lib/python3.9/asyncio/base_events.py", line 510, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
sys:1: RuntimeWarning: coroutine 'Launcher.killChrome' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

Also, it's possible to wmdb request aiosqlite version like 17, not 13-14 version. Thanks, best regards.
pkg_resources.DistributionNotFound: The 'aiosqlite<0.14.0,>=0.13.0' distribution was not found and is required by witnessme

wmdb soft_unicode missing

soft_unicode is depreciated from the markupsafe toolkit and thus wmdb no longer works.

The temporary fix for this issue is to install the older version of markupsafe, in pipx thats done with the following command:
pipx inject witnessme --pip-args install markupsafe==2.0.1

Error calling command 'scan': module 'yaml' has no attribute 'CLoader'

The working environment is Mac OS.

WMDB ≫ scan 1
Traceback (most recent call last):
File "wmdb.py", line 239, in cmdloop
await self.scan()
File "wmdb.py", line 197, in scan
self.signatures.load()
File "/Users/[redacted]/opt/WitnessMe/witnessme/signatures.py", line 15, in load
self.signatures.append(yaml.load(sig, Loader=yaml.CLoader))
AttributeError: module 'yaml' has no attribute 'CLoader'
Error calling command 'scan': module 'yaml' has no attribute 'CLoader'

websocket installation fails during pipenv install --three

I am trying to add WitnessMe to the SamuraiWTF build. We are getting a failure during the set up from pipenv failing to find a matching version of websockets.

Basically the error is:

"ERROR: Could not find a version that satisfies the requirement websocket==8.1" It then lists "from versions" and that only goes to 7.0. This is a Debian system from SamuraiWTF

Allow more than 1 screenshot per host

Hello,

This is a bit of a bug report and a bit (apparently) of a request.

I'd like to pass URL:s from a file into witnessme screenshot and have a screenshot of each URL be generated, saved and the related record be added to the database; however, it is failing to act as I expect or as I wish. :)

For example, I have run gobuster against vulnversity on tryhackme and have saved the output to a file as:

http://10.10.162.217:3333/.htpasswd
http://10.10.162.217:3333/.hta
http://10.10.162.217:3333/.htaccess
http://10.10.162.217:3333/css
http://10.10.162.217:3333/fonts
http://10.10.162.217:3333/images
http://10.10.162.217:3333/index.html
http://10.10.162.217:3333/internal
http://10.10.162.217:3333/js
http://10.10.162.217:3333/server-status

I then invoke witnessme as follows and rcv the following output:

kali@DESKTOP-67BAPDH:~$ cat tcp3333_dirb_common.txt | witnessme --threads 4 screenshot -
[witnessme.screenshot] INFO - Starting scan bcbae438-27be-43c4-990f-714c0eb30d98
[witnessme.headlessbrowser] INFO - Starting headless browser
[witnessme.headlessbrowser] INFO - Using 4 browser tab(s)/thread(s)
[witnessme.screenshot] INFO - Took screenshot of http://10.10.143.64:3333/.htpasswd
[witnessme.screenshot] INFO - Took screenshot of http://10.10.143.64:3333/.hta
[witnessme.screenshot] INFO - Took screenshot of http://10.10.143.64:3333/.htaccess
[witnessme.screenshot] INFO - Took screenshot of http://10.10.143.64:3333/css
[witnessme.headlessbrowser] INFO - Killing headless browser
[witnessme.headlessbrowser] INFO - Starting headless browser
[witnessme.headlessbrowser] INFO - Using 4 browser tab(s)/thread(s)
[witnessme.headlessbrowser] INFO - total: 10, done: 4, pending: 6
[witnessme.screenshot] INFO - Took screenshot of http://10.10.143.64:3333/fonts
[witnessme.screenshot] INFO - Took screenshot of http://10.10.143.64:3333/images
[witnessme.headlessbrowser] INFO - total: 10, done: 6, pending: 4
[witnessme.screenshot] INFO - Took screenshot of http://10.10.143.64:3333/internal
[witnessme.headlessbrowser] INFO - total: 10, done: 7, pending: 3
[witnessme.screenshot] INFO - Took screenshot of http://10.10.143.64:3333/index.html
[witnessme.headlessbrowser] INFO - Killing headless browser
[witnessme.headlessbrowser] INFO - Starting headless browser
[witnessme.headlessbrowser] INFO - Using 2 browser tab(s)/thread(s)
[witnessme.screenshot] INFO - Took screenshot of http://10.10.143.64:3333/js
[witnessme.screenshot] INFO - Took screenshot of http://10.10.143.64:3333/server-status
[witnessme.headlessbrowser] INFO - Killing headless browser
[witnessme.screenshot] INFO - Saved scan to scan_2020_10_17_073824/

The results are very interesting and are as follows:

kali@DESKTOP-67BAPDH:~$ wmdb scan_2020_10_17_073824/
[!] Press tab for autocompletion and available commands
WMDB ≫ servers
+----+------------------------------------+---------------+------------------------+----------------------+
| Id | URL                                | Title         | Server                 | Matched Signature(s) |
+----+------------------------------------+---------------+------------------------+----------------------+
| 1  | http://10.10.143.64:3333/.htpasswd | 403 Forbidden | Apache/2.4.18 (Ubuntu) | None                 |
+----+------------------------------------+---------------+------------------------+----------------------+
WMDB ≫ hosts
+----+--------------+----------+---------------------+----------------------+
| Id | IP           | Hostname | Discovered Services | Matched Signature(s) |
+----+--------------+----------+---------------------+----------------------+
| 1  | 10.10.143.64 |          | 1                   |                      |
+----+--------------+----------+---------------------+----------------------+
WMDB ≫ generate_report
[witnessme.signatures] DEBUG - Loaded 296 signature(s)
[witnessme] DEBUG - Starting signature scan...
[witnessme] DEBUG - Signature scan completed, identified 0 service(s) in 00m00s
[witnessme.reporting] INFO - Generating HTML report, please wait...
[witnessme.reporting] INFO - Done

In the generated report, the URL is noted as it is in id 1 of wmdb servers output (http://10.10.143.64:3333/.htpasswd). However, the screenshot is that of http://10.10.143.64:3333/js; this screenshot is the second to last screenshot noted in witnessme stdout. This is reproducible on demand, and I believe it must be related to the thread logic.

Environmental notes:

  1. I am running this on kali in WSL2, which, as far as I'm aware, is irrelevant and should not cause oddities, as WSL2 is running as a VM within a "lite" version of hyperv.
  2. specifically, I am targeting vulnversity on tryhackme.

If I attempt this with --threads 1, then things appear to be predictable... the noted string is that of the first item (that contained in wmdb servers output). and the last screenshot produced (as noted in the witnessme stdout.

So, I have only have one ask:
This is all sort of weird... but not that weird since you clearly didn't code to support multiple screenshots of URLs from the same host(?). Can you extend support to allow for multiple URLs from the same host?

Thanks

BUG - WMDB scan module not working

Probably a simple installation that I need to run
Command:
WMDB ≫ scan 1

Output:

Traceback (most recent call last):
  File "./wmdb.py", line 239, in cmdloop
    await self.scan()
  File "./wmdb.py", line 197, in scan
    self.signatures.load()
  File "/home/WitnessMe/witnessme/signatures.py", line 15, in load
    self.signatures.append(yaml.load(sig, Loader=yaml.CLoader))
AttributeError: module 'yaml' has no attribute 'CLoader'
Error calling command 'scan': module 'yaml' has no attribute 'CLoader'

BUG - Witnessme stalls when supplying nmap xml file

When you submit a bug and then read the todo github documentation
Support NMap & .nessus files as input (Almost there, still some bugs but usable)

Hi @byt3bl33d3r , Great tool! Wanted to help out the project and try to identify as many bugs as I can.

Background - I ran a nmap scan that created a xml file as output.
Problem - I attempted to run witnessme with a nmap xml file and witnessme would stall and never run.
Command - python witnessme.py nmap.xml and python3 witnessme.py nmap.xml
Output -
... [INFO] - witnessme.py: main - Waiting for queue to populate...

Also I tried to provide witnessme a different nmap format (gnmap and nmap) and it seems witnessme would run various strings not associated with any IPs.

Installation information
fresh kali linux image and Witnessme

git clone https://github.com/byt3bl33d3r/WitnessMe && cd WitnessMe
pip3 install --user pipenv && pipenv install --three
pipenv shell

Screenshot command fails on arm64 (with fix)

The screenshot command fails on arm64 due to the an upstream dependency only pulling down a binary blob for one particular CPU architecture.

Until this is resolved upstream (pyppeteer/pyppeteer#155), consider installing chromium from the OS package manager.

This fix is demonstrated by changing only the Dockerfile, in the forked repo branch at master...kairzha:kairzha-patch-1

You can test this out yourself via:

arm64:

docker run --rm busybox uname -a
Linux a2ca1418e374 5.4.0-1022-raspi #25-Ubuntu SMP PREEMPT TIMESTAMP aarch64 GNU/Linux
docker build --tag witnessmeme https://github.com/kairzha/WitnessMe.git#kairzha-patch-1
docker run --rm -v "$PWD":/data -w /data witnessmeme screenshot 'https://www.bing.com/search?q=apple+m1'
[witnessme.screenshot] INFO - Saved scan to scan_TIMESTAMP/

x64:

docker run --rm busybox uname -a
Linux fb2651a302d5 5.4.39-linuxkit #1 SMP TIMESTAMP x86_64 GNU/Linux
docker build --tag witnessmeme https://github.com/kairzha/WitnessMe.git#kairzha-patch-1
docker run --rm -v "$PWD":/data -w /data witnessmeme screenshot 'https://www.bing.com/search?q=apple+m1'
[witnessme.screenshot] INFO - Saved scan to scan_TIMESTAMP/

Issue downloading result via API

After cloning the source and using the dockerfile.api to create a container, I received a 500 error trying to download the result using the API (tested using the built in swagger ui). I believe line 59 in scan.py needs to be changed...

WitnessMe/witnessme/api/routers/scan.py

@router.get("/{scan_id}/result")
async def get_scan_result(scan_id: uuid.UUID, request: Request):
    scan = request.app.state.SCANS.get(scan_id)
#    if not scan.stats.done:
#change to something like
      if not scan.state in [ScanState.DONE]:

After which I received an error that aiotools needed to be installed. Adding this to requirements.txt resolved this issue.

aiofiles==0.5.0 --hash=sha256:377fdf7815cc611870c59cbd07b68b180841d2a2b79812d8c218be02448c2acb

After which everything worked like a charm. Thanks for the app!

Adding --no-sandbox param to the pyppeteer

When you try to run witness me with root user, pyppeteer will be ignoring to initiate chrome process. In order to avoid from that, we gotta pass args=['--no-sandbox'] to launch() function.

browser = await pyppeteer.launch(headless=True, ignoreHTTPSErrors=True)

I do propose following fix. I've tested it on locally.

browser = await pyppeteer.launch(headless=True, ignoreHTTPSErrors=True, args=['--no-sandbox'])

Add WHOIS results to the report

While investigating domains that match my regex and taking screenshots of them, it would be so helpful to have the WHOIS results next to each screenshot.

Thanks!

Connection to Chrome/Chromium times out after 1k-ish screenshots?

So apparently, there's yet another websocket connection bug in pyppeteer. Seems that after 400ish screenshots the connection to chrome just dies. :(
miyakogi/pyppeteer#149

Tried some of the proposed fixes but none of them worked for me.

[E:pyppeteer.connection] connection unexpectedly closed
2019-11-10 23:19:09,304 [ERROR] - base_events.py: default_exception_handler - Task exception was never retrieved
future: <Task finished name='Task-7697' coro=<Connection._async_send() done, defined at /home/bhis/.local/share/virtualenvs/WitnessMe-QFMsedki/lib/python3.8/site-packages/pyppeteer/connection.py:69> exception=InvalidStateError('invalid state')>
Traceback (most recent call last):
  File "/home/bhis/.local/share/virtualenvs/WitnessMe-QFMsedki/lib/python3.8/site-packages/websockets/protocol.py", line 827, in transfer_data
    message = await self.read_message()
  File "/home/bhis/.local/share/virtualenvs/WitnessMe-QFMsedki/lib/python3.8/site-packages/websockets/protocol.py", line 895, in read_message
    frame = await self.read_data_frame(max_size=self.max_size)
  File "/home/bhis/.local/share/virtualenvs/WitnessMe-QFMsedki/lib/python3.8/site-packages/websockets/protocol.py", line 971, in read_data_frame
    frame = await self.read_frame(max_size)
  File "/home/bhis/.local/share/virtualenvs/WitnessMe-QFMsedki/lib/python3.8/site-packages/websockets/protocol.py", line 1047, in read_frame
    frame = await Frame.read(
  File "/home/bhis/.local/share/virtualenvs/WitnessMe-QFMsedki/lib/python3.8/site-packages/websockets/framing.py", line 105, in read
    data = await reader(2)
  File "/home/bhis/.pyenv/versions/3.8.0/lib/python3.8/asyncio/streams.py", line 738, in readexactly
    raise exceptions.IncompleteReadError(incomplete, n)
asyncio.exceptions.IncompleteReadError: 0 bytes read on a total of 2 expected bytes

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/bhis/.local/share/virtualenvs/WitnessMe-QFMsedki/lib/python3.8/site-packages/pyppeteer/connection.py", line 73, in _async_send
    await self.connection.send(msg)
  File "/home/bhis/.local/share/virtualenvs/WitnessMe-QFMsedki/lib/python3.8/site-packages/websockets/protocol.py", line 555, in send
    await self.ensure_open()
  File "/home/bhis/.local/share/virtualenvs/WitnessMe-QFMsedki/lib/python3.8/site-packages/websockets/protocol.py", line 803, in ensure_open
    raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedError: code = 1006 (connection closed abnormally [internal]), no reason

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/bhis/.local/share/virtualenvs/WitnessMe-QFMsedki/lib/python3.8/site-packages/pyppeteer/connection.py", line 79, in _async_send
    await self.dispose()
  File "/home/bhis/.local/share/virtualenvs/WitnessMe-QFMsedki/lib/python3.8/site-packages/pyppeteer/connection.py", line 170, in dispose
    await self._on_close()
  File "/home/bhis/.local/share/virtualenvs/WitnessMe-QFMsedki/lib/python3.8/site-packages/pyppeteer/connection.py", line 151, in _on_close
    cb.set_exception(_rewriteError(
asyncio.exceptions.InvalidStateError: invalid state

Signature Based on Favicon

There's been a few times on engagements where I only see a blank page, and even X-Powered-By and Server headers are suppressed, but the favicon for the product deployed to the server is still available. I was wondering what you think about adding the ability to signature based on favicons?

I'm thinking it could either be done by a quick MD5 or maybe even CRC32 to help keep performance up. I wanted to get your input on it before I try to code anything up and submit a PR

Errors during nmap XML parsing

I was attempting to run WitnessMe with a large nmap XML file for the top 1000 ports in a certain range. When passing this to WitnessMe (using both pipx and docker) I received the following error:

# docker run -it --entrypoint=/bin/sh -v $(pwd):/transfer a45ee02a44c1
$ witnessme screenshot /transfer/top1000.xml
[witnessme.screenshot] INFO - Starting scan 593de326-9a88-4ee1-9701-305af0bfb66b
Task exception was never retrieved
future: <Task finished name='Task-3' coro=<HeadlessChromium.target_producer() done, defined at /home/appuser/.local/lib/python3.8/site-packages/witnessme/headlessbrowser.py:64> exception=KeyError('port')>
Traceback (most recent call last):
  File "/home/appuser/.local/lib/python3.8/site-packages/witnessme/headlessbrowser.py", line 66, in target_producer
    for url in generated_targets:
  File "/home/appuser/.local/lib/python3.8/site-packages/witnessme/parsers.py", line 198, in generate
    for url in generated_urls:
  File "/home/appuser/.local/lib/python3.8/site-packages/witnessme/parsers.py", line 85, in __enter__
    xmltodict.parse(
  File "/home/appuser/.local/lib/python3.8/site-packages/xmltodict.py", line 325, in parse
    parser.ParseFile(xml_input)
  File "/usr/src/python/Modules/pyexpat.c", line 461, in EndElement
  File "/home/appuser/.local/lib/python3.8/site-packages/xmltodict.py", line 126, in endElement
    should_continue = self.item_callback(self.path, item)
  File "/home/appuser/.local/lib/python3.8/site-packages/witnessme/parsers.py", line 108, in parser_callback
    ports = item["ports"]["port"]
KeyError: 'port'

I was able to use gowitness and it parsed the file normally, so I believe this has something to do with how WitnessMe handles nmap XML parsing.

/transfer running as root and cannot transfer files to host

Using the docker and -v to mount current volume to /transfer directory, I can see that /transfer is owned by root and hence cannot transfer any files from docker into the /transfer folder to take the files outside to the host machine

Doesn't recognize file with urls

Hi, I'm trying to feed it a plain file with urls but it appears it's trying to resolve the filename instead of the actual urls in the file.

 ⚡ root@kali ~/tools/witnessme docker run --rm -ti 0c2b4fbab0b3 /tmp/domains
[witnessme.utils] DEBUG - Patching pyppeteer...
[witnessme.scan] DEBUG - Waiting for queue to populate...
[witnessme.parsers] DEBUG - Detected IP Address/Range/CIDR, hostname or URL as a target
[witnessme.scan] INFO - Starting headless browser
[witnessme.scan] INFO - Using 8 worker thread(s)
[witnessme.scan] ERROR - Error taking screenshot: net::ERR_NAME_NOT_RESOLVED at http:///tmp/domains:8080
[witnessme.scan] ERROR - Error taking screenshot: net::ERR_NAME_NOT_RESOLVED at http:///tmp/domains:443
[witnessme.scan] ERROR - Error taking screenshot: net::ERR_NAME_NOT_RESOLVED at http:///tmp/domains:8443
[witnessme.scan] ERROR - Error taking screenshot: net::ERR_NAME_NOT_RESOLVED at https:///tmp/domains:80
[witnessme.scan] ERROR - Error taking screenshot: net::ERR_NAME_NOT_RESOLVED at https:///tmp/domains:8080
[witnessme.scan] ERROR - Error taking screenshot: net::ERR_NAME_NOT_RESOLVED at https:///tmp/domains:443
[witnessme.scan] ERROR - Error taking screenshot: net::ERR_NAME_NOT_RESOLVED at http:///tmp/domains:80
[witnessme.scan] ERROR - Error taking screenshot: net::ERR_NAME_NOT_RESOLVED at https:///tmp/domains:8443
[witnessme.scan] INFO - Killing headless browser

Tag the source

It would be very helpful if you could tag releases as well. This would enable distributions who want to fetch the source from GitHub instead of PyPI.

Thanks

Unable to load nmap xml output file

Hi, I have a problem loading the nmap xml output file. the tool is stuck with the following output:
2020-01-13 03:15:53,814 [INFO] - witnessme.py: main - Waiting for queue to populate...

Unable to GET/screenshot/{scan_id}/result

hi, i follow all steps to test API (http://127.0.0.1:8000/docs#/), but on step GET/screenshot/{scan_id}/result i have this error:

INFO:     172.17.0.1:60500 - "GET /screenshot/ HTTP/1.1" 200 OK
INFO:     172.17.0.1:60502 - "POST /screenshot/ HTTP/1.1" 200 OK
INFO:     172.17.0.1:60504 - "GET /screenshot/3a2438f3-3c4c-4438-9ed7-44d5ae5c45f2 HTTP/1.1" 200 OK
INFO:     172.17.0.1:60506 - "GET /screenshot/3a2438f3-3c4c-4438-9ed7-44d5ae5c45f2/start HTTP/1.1" 200 OK
2022-02-22 18:57:01,848 [INFO] witnessme.screenshot - screenshot.py: start - Starting scan 3a2438f3-3c4c-4438-9ed7-44d5ae5c45f2
2022-02-22 18:57:01,866 [DEBUG] witnessme.headlessbrowser - headlessbrowser.py: run - Waiting for queue to populate...
2022-02-22 18:57:01,866 [DEBUG] witnessme.parsers - parsers.py: generate - Detected IP Address/Range/CIDR, hostname or URL as a target
2022-02-22 18:57:01,866 [DEBUG] witnessme.parsers - parsers.py: generate - Detected IP Address/Range/CIDR, hostname or URL as a target
2022-02-22 18:57:01,966 [INFO] witnessme.headlessbrowser - headlessbrowser.py: start_browser - Starting headless browser
2022-02-22 18:57:02,052 [INFO] witnessme.headlessbrowser - headlessbrowser.py: start_browser - Using 2 browser tab(s)/thread(s)
2022-02-22 18:57:04,913 [INFO] witnessme.screenshot - screenshot.py: add_to_database - Took screenshot of https://google.com:443
2022-02-22 18:57:04,926 [DEBUG] witnessme.headlessbrowser - headlessbrowser.py: open_browser_tab - Navigated to https://google.com
2022-02-22 18:57:05,983 [INFO] witnessme.screenshot - screenshot.py: add_to_database - Took screenshot of https://opera.com:443
2022-02-22 18:57:05,998 [DEBUG] witnessme.headlessbrowser - headlessbrowser.py: open_browser_tab - Navigated to https://opera.com
2022-02-22 18:57:06,003 [INFO] witnessme.headlessbrowser - headlessbrowser.py: start_browser - Killing headless browser
2022-02-22 18:57:06,023 [INFO] witnessme.screenshot - screenshot.py: start - Saved scan to scan_2022_02_22_185619/
2022-02-22 18:57:27,397 [INFO] witnessme.screenshot - screenshot.py: stop - Stopping scan 3a2438f3-3c4c-4438-9ed7-44d5ae5c45f2
INFO:     172.17.0.1:60510 - "GET /screenshot/3a2438f3-3c4c-4438-9ed7-44d5ae5c45f2/stop HTTP/1.1" 200 OK
INFO:     172.17.0.1:60512 - "GET /screenshot/3a2438f3-3c4c-4438-9ed7-44d5ae5c45f2/result HTTP/1.1" 500 Internal Server Error
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "/home/appuser/.local/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 390, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/home/appuser/.local/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "/home/appuser/.local/lib/python3.8/site-packages/fastapi/applications.py", line 146, in __call__
    await super().__call__(scope, receive, send)
  File "/home/appuser/.local/lib/python3.8/site-packages/starlette/applications.py", line 102, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/home/appuser/.local/lib/python3.8/site-packages/starlette/middleware/errors.py", line 181, in __call__
    raise exc from None
  File "/home/appuser/.local/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "/home/appuser/.local/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in __call__
    raise exc from None
  File "/home/appuser/.local/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "/home/appuser/.local/lib/python3.8/site-packages/starlette/routing.py", line 550, in __call__
    await route.handle(scope, receive, send)
  File "/home/appuser/.local/lib/python3.8/site-packages/starlette/routing.py", line 227, in handle
    await self.app(scope, receive, send)
  File "/home/appuser/.local/lib/python3.8/site-packages/starlette/routing.py", line 41, in app
    response = await func(request)
  File "/home/appuser/.local/lib/python3.8/site-packages/fastapi/routing.py", line 196, in app
    raw_response = await run_endpoint_function(
  File "/home/appuser/.local/lib/python3.8/site-packages/fastapi/routing.py", line 148, in run_endpoint_function
    return await dependant.call(**values)
  File "/home/appuser/.local/lib/python3.8/site-packages/witnessme/api/routers/scan.py", line 59, in get_scan_result
    if not scan.stats.done:
AttributeError: 'BrowserStats' object has no attribute 'done'

Requests pending and no proxy

Good morning,

I encounter issues using witnessme. I don't understand where's the problem. When I try to launch it against a list of IPs in a file, it enters in an infinite loop, pending all the requests :

witnessme -d screenshot urls.txt

image

Same problem if I try only with one IP, or reduce the thread to 1 and timeout to 60 seconds. The chrome process is running when executing the command :

ss -tunltp

image

Moreover, I don't know if this issue is related, but I can't proxify the trafic :

HTTP_PROXY=http://127.0.0.1:8080 witnessme -d screenshot urls.txt

[witnessme.utils] DEBUG - Patching pyppeteer...
[witnessme] DEBUG - {'threads': 15, 'timeout': 15, 'debug': True, 'command': 'screenshot', 'target': ['urls.txt'], 'ports': [80, 8080, 443, 8443], 'func': <function screenshot at 0x7f20904152d0>}
[witnessme.screenshot] INFO - Starting scan 0e26de7e-b6fe-45e1-8e0c-6d9105a27b53
[witnessme.headlessbrowser] DEBUG - Waiting for queue to populate...
[witnessme.parsers] DEBUG - Detected file as a target
[witnessme.headlessbrowser] INFO - Starting headless browser
[witnessme.headlessbrowser] INFO - Proxy set to http://127.0.0.1:8080
Traceback (most recent call last):
  File "/home/t0/.local/bin/witnessme", line 8, in <module>
    sys.exit(run())
  File "/home/t0/.local/pipx/venvs/witnessme/lib/python3.10/site-packages/witnessme/console/witnessme.py", line 113, in run
    args.func(args)
  File "/home/t0/.local/pipx/venvs/witnessme/lib/python3.10/site-packages/witnessme/utils.py", line 41, in wrapper
    return asyncio.run(f(*args, **kwargs))
  File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.10/asyncio/base_events.py", line 641, in run_until_complete
    return future.result()
  File "/home/t0/.local/pipx/venvs/witnessme/lib/python3.10/site-packages/witnessme/console/witnessme.py", line 19, in screenshot
    await cmd.start()
  File "/home/t0/.local/pipx/venvs/witnessme/lib/python3.10/site-packages/witnessme/commands/screenshot.py", line 124, in start
    await self._scan_task
  File "/home/t0/.local/pipx/venvs/witnessme/lib/python3.10/site-packages/witnessme/commands/screenshot.py", line 118, in setup_and_run
    await self._browser.run(self.target, self.ports)
  File "/home/t0/.local/pipx/venvs/witnessme/lib/python3.10/site-packages/witnessme/headlessbrowser.py", line 149, in run
    await self.start_browser(
  File "/home/t0/.local/pipx/venvs/witnessme/lib/python3.10/site-packages/witnessme/headlessbrowser.py", line 107, in start_browser
    browser = await pyppeteer.launch(
  File "/home/t0/.local/pipx/venvs/witnessme/lib/python3.10/site-packages/pyppeteer/launcher.py", line 306, in launch
    return await Launcher(options, **kwargs).launch()
  File "/home/t0/.local/pipx/venvs/witnessme/lib/python3.10/site-packages/pyppeteer/launcher.py", line 167, in launch
    self.browserWSEndpoint = get_ws_endpoint(self.url)
  File "/home/t0/.local/pipx/venvs/witnessme/lib/python3.10/site-packages/pyppeteer/launcher.py", line 229, in get_ws_endpoint
    data = json.loads(f.read().decode())
  File "/usr/lib/python3.10/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.10/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.10/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

It seems it tries to access to http://127.0.0.1:<port_of_headless_chrome>/json/version, but can't reach it :

image

I installed witnessme using pipx following the README.

System : Arch Linux 5.16.1-arch1-1 x86_64 GNU/Linux

Build fails on arm64 due to httptools pip package

x64:

$ docker run --rm busybox uname -a
Linux 21232f7f703d 5.4.39-linuxkit #1 SMP TIMESTAMP x86_64 GNU/Linux
$ docker build --tag witnessme https://github.com/byt3bl33d3r/WitnessMe.git
[+] Building TIMEDURATION (13/13) FINISHED 

arm64:

$ docker run --rm busybox uname -a
Linux 790f4ba88c53 5.4.0-1022-raspi #25-Ubuntu SMP PREEMPT TIMESTAMP aarch64 GNU/Linux
$ docker build --tag witnessme https://github.com/byt3bl33d3r/WitnessMe.git
Building wheel for httptools (setup.py): started                                                      
  Building wheel for httptools (setup.py): finished with status 'error'                                 
  ERROR: Command errored out with exit status 1:                                                        
   command: /usr/local/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-i
nstall-tabquj4g/httptools/setup.py'"'"'; __file__='"'"'/tmp/pip-install-tabquj4g/httptools/setup.py'"'"'
;f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"')
;f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-ijz37d6j        
       cwd: /tmp/pip-install-tabquj4g/httptools/                                                        
  Complete output (30 lines):                     
....etc....
The command '/bin/sh -c pip3 install -r requirements.txt' returned a non-zero code: 1

Most probable cause is tagging a binary blob for a specific architecture. In this case, it appears there is a problem with your upstream httptools pip package not having a prebuilt wheel for this architecture, and your base docker image does not have the required build tools.

x64:

$ docker run -it --rm python:3.8-slim bash
pip3 install httptools==0.1.1
Collecting httptools==0.1.1
  Downloading httptools-0.1.1-cp38-cp38-manylinux1_x86_64.whl (227 kB)
     |████████████████████████████████| 227 kB 3.3 MB/s 
Installing collected packages: httptools
Successfully installed httptools-0.1.1

arm64:

$ docker run -it --rm python:3.8-slim bash
pip3 install httptools==0.1.1                                                      
Collecting httptools==0.1.1                                                                             
  Downloading httptools-0.1.1.tar.gz (106 kB)                                                           
     |████████████████████████████████| 106 kB 1.6 MB/s                                                 
Building wheels for collected packages: httptools                                                       
  Building wheel for httptools (setup.py) ... error 
  ERROR: Command errored out with exit status 1:  

This pip package installs correctly using the full-size base image instead of slim:

arm64:

docker run -it --rm python:3.8 bash
pip3 install httptools==0.1.1  
Collecting httptools==0.1.1
  Downloading httptools-0.1.1.tar.gz (106 kB)
     |████████████████████████████████| 106 kB 2.1 MB/s 
Building wheels for collected packages: httptools
  Building wheel for httptools (setup.py) ... done
  Created wheel for httptools: filename=httptools-0.1.1-cp38-cp38-linux_aarch64.whl size=278614 sha256=c9035d9d96782c9b8e55aa09decf4c30bb7d57497717deb2a5d78ae0087adff0
  Stored in directory: /root/.cache/pip/wheels/16/d9/1d/1cc7690d9e6ef93fcaed984a4f46cedd1d55e8ba03c1ccc48f
Successfully built httptools
Installing collected packages: httptools
Successfully installed httptools-0.1.1

Forking the repo and only changing the docker base image to be python:3.8 instead of python:3.8-slim: master...kairzha:master

arm64:

docker build --tag witnessmek https://github.com/kairzha/WitnessMe.git
Successfully tagged witnessmek:latest

Ability to output to CSV or XML --feature request

The tool makes a very useful graph output. Would it be possible to leverage it in another format that is shareable to people that don't have WitnessMe installed?

Specifically, I was hoping for a CSV or XML output.

PermissionError: [Errno 13] Permission denied: in docker container

Hi, i run docker with docker run --rm -ti --entrypoint=/bin/sh $IMAGE_ID
but, i don't have enough rights to run witnessme screenshot https://google.com, how to fix it?

$ witnessme screenshot https://google.com
[witnessme.screenshot] INFO - Starting scan 0ba5b46f-4349-4535-a3ab-1dd522fa9373
Traceback (most recent call last):
  File "/home/appuser/.local/bin/witnessme", line 8, in <module>
    sys.exit(run())
  File "/home/appuser/.local/lib/python3.8/site-packages/witnessme/console/witnessme.py", line 113, in run
    args.func(args)
  File "/home/appuser/.local/lib/python3.8/site-packages/witnessme/utils.py", line 41, in wrapper
    return asyncio.run(f(*args, **kwargs))
  File "/usr/local/lib/python3.8/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/local/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "/home/appuser/.local/lib/python3.8/site-packages/witnessme/console/witnessme.py", line 19, in screenshot
    await cmd.start()
  File "/home/appuser/.local/lib/python3.8/site-packages/witnessme/commands/screenshot.py", line 128, in start
    await self._scan_task
  File "/home/appuser/.local/lib/python3.8/site-packages/witnessme/commands/screenshot.py", line 114, in setup_and_run
    os.mkdir(self.report_folder)
PermissionError: [Errno 13] Permission denied: 'scan_2022_02_22_180619'

Consider using pyppeteer2

It looks like pyppeteer has been abandoned, but pyppeteer2 seems to have fixed some of the worst issues with pyppeteer

Error During Chromium Download

Hello,

I'm getting the below error on first run, is there any workaround to obtain chromium for use with WitnessMe?

[witnessme.screenshot] INFO - Starting scan 03393d86-5f57-4983-993d-d89c2a616521
[witnessme.headlessbrowser] INFO - Starting headless browser
[W:pyppeteer.chromium_downloader] start chromium download.
Download may take a few minutes.
Traceback (most recent call last):
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/connectionpool.py", line 670, in urlopen
httplib_response = self._make_request(
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/connectionpool.py", line 381, in _make_request
self._validate_conn(conn)
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/connectionpool.py", line 978, in validate_conn
conn.connect()
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/connection.py", line 362, in connect
self.sock = ssl_wrap_socket(
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/util/ssl
.py", line 384, in ssl_wrap_socket
return context.wrap_socket(sock, server_hostname=server_hostname)
File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "/usr/lib/python3.8/ssl.py", line 1040, in _create
self.do_handshake()
File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
ConnectionResetError: [Errno 104] Connection reset by peer

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/root/.local/bin/witnessme", line 8, in
sys.exit(run())
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/witnessme/console/witnessme.py", line 113, in run
args.func(args)
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/witnessme/utils.py", line 41, in wrapper
return asyncio.run(f(*args, **kwargs))
File "/usr/lib/python3.8/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
return future.result()
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/witnessme/console/witnessme.py", line 19, in screenshot
await cmd.start()
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/witnessme/commands/screenshot.py", line 124, in start
await self._scan_task
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/witnessme/commands/screenshot.py", line 118, in setup_and_run
await self._browser.run(self.target, self.ports)
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/witnessme/headlessbrowser.py", line 149, in run
await self.start_browser(
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/witnessme/headlessbrowser.py", line 107, in start_browser
browser = await pyppeteer.launch(
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/pyppeteer/launcher.py", line 305, in launch
return await Launcher(options, **kwargs).launch()
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/pyppeteer/launcher.py", line 119, in init
download_chromium()
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/pyppeteer/chromium_downloader.py", line 146, in download_chromium
extract_zip(download_zip(get_url()), DOWNLOADS_FOLDER / REVISION)
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/pyppeteer/chromium_downloader.py", line 85, in download_zip
data = http.request('GET', url, preload_content=False)
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/request.py", line 75, in request
return self.request_encode_url(
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/request.py", line 97, in request_encode_url
return self.urlopen(method, url, **extra_kw)
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/poolmanager.py", line 336, in urlopen
response = conn.urlopen(method, u.request_uri, **kw)
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/connectionpool.py", line 754, in urlopen
return self.urlopen(
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/connectionpool.py", line 754, in urlopen
return self.urlopen(
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/connectionpool.py", line 754, in urlopen
return self.urlopen(
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/connectionpool.py", line 726, in urlopen
retries = retries.increment(
File "/root/.local/pipx/venvs/witnessme/lib/python3.8/site-packages/urllib3/util/retry.py", line 439, in increment
raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='storage.googleapis.com', port=443): Max retries exceeded with url: /chromium-browser-snapshots/Linux_x64/588429/chrome-linux.zip (Caused by ProtocolError('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer')))

Nmap/Nessus file upload through api

First off, very cool project 😁 I enjoy most of the stuff you do 🥳 so thank you for doing this! 🙏

I was curious if there was a reason for not exposing ( from what I can see in the fastapi docs page ) uploading a nmap/nessus file?

I noticed you have the functionality already there from the CLI perspective, but is there a limitation for exposing that through the API?

Task id 404 Not Found

Hi, Why if i run in docker witnessme screenshot https://google.com i received task id : 5e685058-8916-4a13-8564-9e928efedbff
but after running wmapi and i want to get results about recenlty received task id, i have error 404 Not Found, it's not same task id or?

$ witnessme screenshot https://google.com
[witnessme.screenshot] INFO - Starting scan 5e685058-8916-4a13-8564-9e928efedbff
[witnessme.headlessbrowser] INFO - Starting headless browser
[witnessme.headlessbrowser] INFO - Using 1 browser tab(s)/thread(s)
[witnessme.screenshot] INFO - Took screenshot of https://google.com:443
[witnessme.headlessbrowser] INFO - Killing headless browser
[witnessme.screenshot] INFO - Saved scan to scan_2022_02_22_234054/
$ ls
scan_2022_02_22_234054 src
$ cd scan_2022_02_22_234054
$ ls
https_google.com_443.png  witnessme.db
$ wmapi 0.0.0.0 8000
INFO:     Started server process [70]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO:     172.17.0.1:60650 - "GET /docs HTTP/1.1" 200 OK
INFO:     172.17.0.1:60650 - "GET /openapi.json HTTP/1.1" 200 OK
INFO:     172.17.0.1:60652 - "GET /screenshot/ HTTP/1.1" 200 OK
INFO:     172.17.0.1:60654 - "GET /screenshot/5e685058-8916-4a13-8564-9e928efedbff/result HTTP/1.1" 404 Not Found

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.