
Weaponized Browser-in-the-Middle (BitM) for Penetration Testers

Weaponized multi-user browser-in-the-middle (BitM) for penetration testers. This attack can be used to bypass multi-factor authentication on many high-value web applications. It even works for applications that do not use session tokens, and therefore would not be exploitable using traditional token stealing attacks. This is a social engineering tool and does not exploit any technical flaws in the target service.
This tool is a specialized web server. It is designed to run on a Debian 11 (Bullseye) Linux server and relies on public IP information to protect the admin functionality. Don't expect to be able to test locally without jumping through some serious hoops.
Warning: Chromium is not supported on ARM. While it is technically possible to force the use of an ARM chromium binary, you will lose all the additional features/protections of puppeteer-extra.
This example setup utilizes Caddy to handle TLS, SNI, and add a couple of custom headers like 'X-Real-IP' to each request. You don't have to use Caddy with Cuddlephish, as the same reverse proxy can be set up using Nginx, Apache, etc. I just like Caddy because it is easy to install with Docker, and has plugins to manage Letsencrypt certs for most domain registrars. The example Caddyfile shows how you would set it up for Gandi. Check the docs for your registrar.
Install Docker, Node, XVFB, and some other dependencies:
git clone https://github.com/fkasler/cuddlephish
cd cuddlephish
sudo bash install_deps.sh
You can then use Docker to build Caddy with a wildcard cert plugin for your registrar. The example is for Gandi. Check the docs here and the list of dns provider modules here. You can mod the Dockerfile for your registrar before building:
sudo docker build -t caddy .
Now mod the Caddyfile to swap your domain and Gandi (or other registrar) API key, and start Caddy. I recommend starting this in a screen or tmux window so that you can run the Node server in another window in a moment:
sudo docker run -p 80:80 -p 443:443 -p 2019:2019 -v $PWD/Caddyfile:/etc/caddy/Caddyfile --network=host caddy:latest
With Caddy fielding traffic for us on 80 and 443, we can finally run the tool!
Install the Node dependencies:
npm install
A few config tweaks: CRITICAL STEP: Make sure to mod the example config.json to add your approved public IP(s) for admin access. This whitelist of IPs is what dictates access to the "/admin" web interface. You should also change the default socket key to something more secure.
The tool is not set up to target any logins by default so you will need to add some. There is an 'add_target.js' script to make this step easy. Just run the script and paste in the URL of the login portal you would like to target when prompted:
node add_target.js
This will grab the service name, tab title, and favicon for you and add an entry to 'targets.json'. You can run this script multiple times and it will append your new targets. The script will name each service based on the domain, without the top level. So, for 'https://www.example.com/login.php' the service would just be 'example' when specifying your target when you...
Run it!
node index.js example
After a few seconds, you should see a message in the console when your first automated Chrome instance checks in over websockets. Now visitors to your phishing site should see what appears to be the target login page but is actually a video feed of your automated browser instance. They can also interact with your browser instance and log in for you.
If you properly configured your admin IP(s) in the config.json, you should be able to view a special '/admin' web interface to track users, view key logs, takeover control of logged in browser instances, steal cookies, and delete unwanted browser instances.
Note: You will not see anything in the admin page until you have some victims. Once you have a victim, their browser instance should pop up on the admin UI.
I have had several people open issues about a "Blank White Page", which is more of a symptom of many possible issues, and not an issue in itself. Please do not open issues under vague symptom names. Instead, if you have a blank page on the user side, try first looking into the following:
At a high level, if you just see a blank page on the front-end, then it means there is some breakdown occuring in the chain of data flow from "Start WebRTC" > "Select Tab to Broadcast" > "Negotiate ICE with Vicitim's Browser" > "Stream Video". The above troubleshooting steps are intended to help you follow the data through this process. When working properly, you should expect to see a log stream on the server similar to the following:
I hope this helps with any issues, and as always, sufficient information to consistently replicate an issue is a prerequisite for submitting issues for further investigation.
Manually trigger a payload to download to the victim's system via JavaScript. Each target starts off with 'payload.txt' as a test payload. Just swap the file location in targets.json to send a custom payload.
Sends a window.location change to the victim to send them to the real login portal. It will seem like they are just being forced to re-authenticate and prevent them from watching you take the controls. If you mod the code, you could do some other fancy things with this general technique ;)