GoCertMITM is a security testing tool for identifying TLS certificate validation vulnerabilities in applications and systems. It acts as a man-in-the-middle proxy that can test various certificate validation scenarios.
-
Multiple Testing Methodologies: Test applications against different certificate validation vulnerabilities:
- Self-signed certificates: Tests if clients accept certificates signed by themselves
- Replaced key certificates: Tests if clients verify the certificate's public key
- Real certificates: Tests if clients accept valid certificates for different domains
- Real certificates as CA: Tests if clients accept certificates signed by valid but unauthorized CAs
-
Network Configuration: Automatically configures the network to intercept connections:
- Acts as a network gateway for client devices
- Uses iptables to redirect HTTPS traffic
- Provides comprehensive testing without client modifications
- Accepts any certificate presented by target servers (including invalid or self-signed certificates)
-
Comprehensive Logging: Detailed logging and reporting:
- Real-time console output for immediate feedback
- Detailed logs of intercepted data for analysis
- Structured storage of test results for reporting
- Go 1.18 or higher
- iptables (for traffic redirection)
- Root/sudo privileges (for network configuration)
-
Clone the repository:
git clone https://github.com/gocertmitm/gocertmitm.git cd gocertmitm -
Build the application:
make build -
Run tests:
make test
You can also run GoCertMITM using Docker:
-
Build the Docker image:
make docker-build -
Run the Docker container:
make docker-run
./certmitm -listen :8080 -listens :8443 -verbose
-listen: Address to listen on for HTTP proxy (default: ":8080")-listens: Address to listen on for HTTPS proxy (default: ":8443")-verbose: Enable verbose logging (operational details)-debug: Enable debug logging (developer information)-certdir: Directory to store generated certificates (default: "./certs")-logdir: Directory to store logs (default: "./logs")-payloaddir: Directory to store request/response payloads (default: "./payloads")-savepayloads: Enable saving of request/response payloads (default: true)-testtype: Test type to start with (default: "self-signed")self-signed: Test if clients accept self-signed certificates (Type 0)replaced-key: Test if clients verify the certificate's public key (Type 1)real-cert: Test if clients accept valid certificates for different domains (Type 2)real-ca: Test if clients accept certificates signed by valid but unauthorized CAs (Type 3)- When auto-testing is disabled, only this test type will be used
- When auto-testing is enabled, this test type will be tried first, followed by the others
-autotest: Automatically test all methods for each domain (default: true)- When enabled, the tool will try each test method for each domain until one succeeds
- If all tests fail, the tool will provide a direct tunnel to the target server
- Results are cached per domain, so successful tests are remembered
- The test order is determined by the
-testtypeflag, with the specified type tried first
-maxattempts: Maximum number of attempts for each test type before moving to the next test (default: 1)- Increase this value if you want to retry a test type multiple times before moving on
- Higher values can be useful for unstable connections or intermittent failures
- Setting to 1 ensures the tool moves quickly through test types
To use GoCertMITM as a man-in-the-middle proxy, you need to:
- Configure the tool as a network gateway
- Redirect HTTPS traffic to the proxy
- Configure client devices to use the proxy as their gateway
For the Direct Tunnel mechanism to work correctly, the traffic redirection must be done on the same host where the proxy is running. We provide scripts to set up and tear down the necessary firewall rules:
# Set up firewall rules to intercept traffic from a specific IP (default: 192.168.82.118)
sudo ./scripts/setup_firewall.sh --target 192.168.82.118
# For more options, use the help flag
sudo ./scripts/setup_firewall.sh --help
# Start the proxy on port 9900
./certmitm -listens :9900 -verbose
# When done, tear down the firewall rules (use the same target IP if customized)
sudo ./scripts/teardown_firewall.sh --target 192.168.82.118The setup script:
- Enables IP forwarding
- Saves the original iptables rules for restoration
- Sets up DNAT (Destination NAT) to redirect port 443 traffic from a specific IP to localhost:9900
- Configures IP masquerading for proper transparent proxying
- Ensures all traffic flows normally except for port 443 traffic from the target IP
- Adds connection marking for proper routing
- Allows customization of the target IP, proxy port, and proxy IP
The teardown script:
- Restores the original iptables rules
- Restores the original IP forwarding setting
- Cleans up any temporary files created during setup
- Accepts the same parameters as the setup script for consistency
Note: These scripts require root privileges to modify system settings. The target IP should be the IP address of the device whose traffic you want to intercept (e.g., the WAN side of an OpenWRT router). The setup script automatically detects your primary network interface for proper configuration.
For proper testing, you need to install the GoCertMITM CA certificate on client devices:
- Copy the
ca.crtfile to the client device - Double-click the certificate file
- Select "Install Certificate"
- Select "Current User" and click "Next"
- Select "Place all certificates in the following store"
- Click "Browse" and select "Trusted Root Certification Authorities"
- Click "Next" and then "Finish"
- Copy the
ca.crtfile to the client device - Double-click the certificate file to open it in Keychain Access
- Add the certificate to the System keychain
- Find the certificate in the list, double-click it
- Expand the "Trust" section
- Change "When using this certificate" to "Always Trust"
- Close the window and enter your password to confirm
- Email the
ca.crtfile to the device or host it on a web server - Open the file on the device
- Follow the prompts to install the profile
- Go to Settings > General > About > Certificate Trust Settings
- Enable full trust for the GoCertMITM root certificate
- Copy the
ca.crtfile to the device - Go to Settings > Security > Install from storage
- Select the certificate file
- Follow the prompts to install the certificate
- Copy the
ca.crtfile to/usr/local/share/ca-certificates/ - Run
sudo update-ca-certificates
Firefox uses its own certificate store:
- Open Firefox
- Go to Options/Preferences
- Search for "certificates"
- Click "View Certificates"
- Go to the "Authorities" tab
- Click "Import" and select the
ca.crtfile - Check "Trust this CA to identify websites" and click "OK"
GoCertMITM manages most certificate operations automatically, but certain tests require specific files:
By default, all certificates are stored in the ./certs directory (configurable with the -certdir flag):
./certs/
├── ca.crt # The GoCertMITM root CA certificate (auto-generated on first run)
├── ca.key # The GoCertMITM root CA private key (auto-generated on first run)
├── self-signed/ # Self-signed certificates
│ └── example.com/ # Domain-specific directory
│ ├── cert.pem # Generated certificate
│ └── key.pem # Private key
├── replaced-key/ # Replaced key certificates
│ └── example.com/
│ ├── cert.pem
│ └── key.pem
├── real/ # Real certificates for different domains
│ └── example.com/
│ ├── cert.pem
│ ├── fullchain.pem
│ └── key.pem
└── real-ca/ # Real certificates used as CAs
└── example.com/
├── cert.pem
└── key.pem
- The root CA certificate and key are automatically generated on first run if they don't exist
- You should install the
ca.crtfile as a trusted root CA on test devices to avoid certificate warnings - All generated certificates are cached in memory during runtime and saved to disk for reuse
- Certificates are organized by test type and domain for efficient retrieval
-
Self-signed Certificates Test:
- No additional files required
- Certificates are generated dynamically during testing
-
Replaced Key Certificates Test:
- No additional files required
- Certificates are generated dynamically during testing
-
Real Certificates Test:
- Requires at least one valid certificate to be used in testing
- Place these certificates in the following structure:
./certs/real/ ├── example.com/ │ ├── cert.pem # Leaf certificate for example.com │ ├── fullchain.pem # Full certificate chain (leaf + intermediates) │ └── key.pem # Private key for example.com certificate └── other-domain.com/ ├── cert.pem # Leaf certificate for other-domain.com ├── fullchain.pem # Full certificate chain (leaf + intermediates) └── key.pem # Private key for other-domain.com certificate- The
fullchain.pemfile is strongly recommended and should contain the complete certificate chain - If
fullchain.pemis not available, the tool will fall back to usingcert.pem - When a client connects to a domain, the tool will:
- First try to use a real certificate for that specific domain if available
- If no certificate exists for that domain, it will use any available real certificate
- If no real certificates are found at all, it falls back to using a CA-signed certificate
- Only one real certificate is required for testing, regardless of how many domains you're testing
- The tool supports both PKCS1 and PKCS8 private key formats
- Certificate and key files must be in PEM format
-
Real Certificates as CA Test:
- Requires valid certificates to be used as unauthorized CAs
- Place these certificates in the following structure:
./certs/ca/ ├── example-ca.com/ │ ├── cert.pem # Valid certificate to be used as CA │ └── key.pem # Private key for the certificate └── other-ca.com/ ├── cert.pem # Valid certificate to be used as CA └── key.pem # Private key for the certificate- When a client connects, the tool will use the specified certificate as a CA to sign the generated certificate
- If no CA certificate is found for the specified domain, it falls back to using the default CA
All certificates and keys should be in PEM format:
- Certificates should begin with
-----BEGIN CERTIFICATE----- - Private keys should begin with
-----BEGIN PRIVATE KEY-----or-----BEGIN RSA PRIVATE KEY-----
For testing purposes, you can:
- Use self-signed certificates (automatically generated)
- Use certificates from your own domains
- Export certificates from browsers for domains you control
- Use test/development certificates from services like Let's Encrypt
Note: Only use certificates for domains you control or have permission to test. Using certificates for unauthorized domains may violate terms of service and legal regulations.
To set up the required directory structure for certificates, you can use the provided setup script:
# Run the setup script
./scripts/setup_cert_dirs.shOr manually create the directories:
# Create the main certificate directory
mkdir -p certs
# Create directories for real certificates
mkdir -p certs/real/example.com
mkdir -p certs/real/other-domain.com
# Create directories for CA certificates
mkdir -p certs/ca/example-ca.com
mkdir -p certs/ca/other-ca.comThen place your certificate files in the appropriate directories as described above.
GoCertMITM implements four main testing approaches to identify different types of certificate validation vulnerabilities. The tool can automatically try all methods for each domain until one succeeds, or you can manually select a specific test type:
This test determines if clients accept certificates that are signed by themselves rather than by a trusted Certificate Authority (CA).
How it works:
- GoCertMITM generates a certificate where the issuer and subject are identical
- The certificate is signed using its own private key
- This certificate is presented to the client during the TLS handshake
Security implications:
- Clients that accept self-signed certificates bypass a fundamental security check in the PKI system
- Attackers can easily generate self-signed certificates for any domain
- This vulnerability allows for trivial man-in-the-middle attacks without needing access to trusted CAs
Common vulnerable scenarios:
- Development environments with security checks disabled
- Applications with improper certificate validation
- Applications with "accept all certificates" options enabled
This test verifies if clients properly validate the public key in certificates, detecting key mismatches between the expected and presented certificates.
How it works:
- GoCertMITM obtains or generates a valid certificate chain for a domain
- It then replaces the public key in the certificate with a different one
- The modified certificate is signed by the GoCertMITM CA
- This certificate is presented to the client during the TLS handshake
Security implications:
- Clients that don't verify public keys are vulnerable to attacks where an attacker has compromised a private key
- Even if certificate pinning is implemented, not checking the public key renders this protection ineffective
- Allows attackers to use stolen certificates with their own private keys
Common vulnerable scenarios:
- Applications with incomplete certificate pinning implementations
- Custom TLS implementations that don't verify all certificate properties
- Mobile applications with simplified certificate validation
This test checks if clients properly validate that the certificate's domain matches the domain they're connecting to.
How it works:
- GoCertMITM presents a valid certificate for domain A when the client is connecting to domain B
- The certificate is completely valid and trusted, but for the wrong domain
- This tests the client's domain validation logic
Security implications:
- Clients that accept certificates for different domains are vulnerable to domain confusion attacks
- Attackers with a valid certificate for one domain could intercept traffic for another domain
- This bypasses the domain-specific protection provided by the PKI system
Common vulnerable scenarios:
- Applications that only check certificate validity but not the domain
- Misconfigured hostname verification
- Applications with wildcard certificate validation issues
This test determines if clients accept certificates signed by valid but unauthorized Certificate Authorities.
How it works:
- GoCertMITM uses a valid certificate from a legitimate website as if it were a CA
- It then generates and signs new certificates using this "CA"
- These certificates are presented to clients during the TLS handshake
Security implications:
- Clients that accept any valid certificate as a CA undermine the entire CA trust model
- Attackers who obtain any valid certificate could generate certificates for any domain
- This vulnerability effectively breaks the hierarchical trust model of PKI
Common vulnerable scenarios:
- Applications with improper CA validation
- Custom certificate stores with incorrect trust settings
- Applications that don't properly validate the certificate chain
These four testing approaches comprehensively cover the most common certificate validation vulnerabilities while keeping the testing process efficient. By testing against these specific scenarios, GoCertMITM can identify weaknesses in TLS implementations that could be exploited by attackers to perform man-in-the-middle attacks.
When auto-testing is enabled (the default), GoCertMITM will:
- Track each domain that clients attempt to connect to
- Try each test method in sequence until one succeeds
- Remember successful tests for each domain
- Provide a direct tunnel if all tests fail
The testing process works as follows:
- When a client first connects to a domain, the tool starts with the test type specified by the
-testtypeflag - If the client accepts the certificate (successful MITM), the tool remembers this for future connections
- If the client rejects the certificate (TLS handshake failure), the tool:
- Detects the handshake error and extracts the domain name
- Records the failure for the current test type
- Automatically moves to the next test type
- Logs the progression through test types
- Ensures IP addresses are not mistakenly treated as domains
- This process continues until either:
- A test succeeds (vulnerability found)
- All tests fail (secure client)
- If all tests fail, subsequent connections to the same domain will use a direct tunnel
The tool tracks failed handshakes per domain and test type, ensuring that it doesn't repeatedly try tests that have already failed. This allows it to efficiently progress through the test types until it finds a vulnerability or determines that the client is secure.
Results are cached per domain, so successful tests are remembered for future connections to the same domain.
The logging system provides:
- Real-time console output for immediate feedback
- Detailed logs of intercepted data for analysis
- Structured storage of test results for reporting
GoCertMITM uses four distinct log levels to provide appropriate information for different use cases:
- ERROR: Critical issues that affect functionality (always displayed)
- INFO: Important operational information (always displayed)
- VERBOSE: Detailed operational information (enabled with
-verbose) - DEBUG: Developer debugging information (enabled with
-debug)
You can control the verbosity of logging with command-line flags:
# Default logging (ERROR and INFO only)
./certmitm
# Enable verbose logging for operational details
./certmitm -verbose
# Enable debug logging for developer information
./certmitm -debug
# Enable both verbose and debug logging
./certmitm -verbose -debugGoCertMITM can save the full request and response payloads for each intercepted connection:
- Each target domain gets its own directory under the payload directory
- Request and response bodies are saved as separate files
- Metadata files contain headers and other information
- Timestamps and client IPs are included in filenames for easy tracking
- Works with all certificate testing methods, including self-signed certificates
./payloads/
├── example.com/ # Domain-specific directory
│ ├── req_20230601_120000.000_192.168.1.2.meta # Request metadata
│ ├── req_20230601_120000.000_192.168.1.2.body # Request body
│ ├── resp_20230601_120000.000_192.168.1.2.meta # Response metadata
│ └── resp_20230601_120000.000_192.168.1.2.body # Response body
└── other-domain.com/ # Another domain
├── req_20230601_120500.000_192.168.1.2.meta
├── req_20230601_120500.000_192.168.1.2.body
├── resp_20230601_120500.000_192.168.1.2.meta
└── resp_20230601_120500.000_192.168.1.2.body
Metadata files contain important information about the request or response:
- Timestamp
- Client IP address
- HTTP method (for requests)
- Status code (for responses)
- Host and path
- All headers
- Body size and filename (if body exists)
Payload logging is enabled by default but can be disabled:
# Disable payload logging
./certmitm -savepayloads=false
# Change payload directory
./certmitm -payloaddir=/path/to/payloadsYou can use the provided script to set up the initial payload directory structure:
# Run the setup script
./scripts/setup_payload_dirs.shThis will create the base directory structure. Additional domain directories will be created automatically as needed during operation.
- Add support for additional certificate validation tests
- Improve error handling for edge cases
- Enhance documentation with more examples
- Add support for upstream proxies
- Develop a web interface for easier result analysis
- Add support for automated testing of specific applications
- Implement pre-generation of certificates for faster testing
- Create reporting templates for vulnerability disclosure
- Expand to support additional protocols beyond HTTPS
- Develop plugins for popular security testing frameworks
- Create a database of known vulnerable applications
- Provide automated remediation recommendations
This project is licensed under the MIT License - see the LICENSE file for details.
- Inspired by the need for better TLS security testing tools
- Thanks to all contributors and the security research community