Last active
December 29, 2023 03:13
-
-
Save vgmoose/215b6006bcc491891998026768e3872b to your computer and use it in GitHub Desktop.
Revisions
-
vgmoose revised this gist
Dec 29, 2023 . 1 changed file with 5 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -152,3 +152,8 @@ On macOS, the GUI in Keychain Access looks as follows:  And upon closing the dialogue after choosing "Always Trust", it should prompt you for your password. ### Using it on iOS To trust the certificate on iOS, it will need to be converted to a [Profile](https://support.apple.com/en-us/102390) using a Mac and [Apple Configurator](https://support.apple.com/apple-configurator). This can be done under File -> New Profile, Certificates, and then import the DER file, save and send to your iOS device. -
vgmoose created this gist
Dec 29, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,154 @@ ## What is this? If you run a local DNS server on your network already (such as a [Pi-hole](https://pi-hole.net)), you can use these instructions to set up an HTTPS redirect for certain sites/domains to other ones. This is particularly useful, for instance, if you don't want to visit Twitter anymore but still occasionally want to automatically view content on it through [Nitter](https://nitter.net). This can be more easily accomplished via [browser extensions](https://addons.mozilla.org/en-US/firefox/addon/nitter-redirect/), but this method is an option to get it on all devices on the network, as long as you trust the cert. Is this a bad idea security wise? Probably! But if you want to try it, here you go: ## Requirements - DNS server running, and point `twitter.com` to your local network IP (eg. `192.168.0.123`) - Nginx server installed and running on the same server ## Instructions These are a shortened/summarized version of my [mitm-nginx gist](https://gist.github.com/vgmoose/125271f1d9e4a1269454a64095b9e4a1), which was intended for use with a Wii U. That gist contains other information about how to run a DNS server or local access point. ### Generate Root CA Certificate The custom Root CA is what will be installed on the target device to allow it to trust our MITM server. The target device ships with a bunch of root CA's in order to know which notable signed certificates to trust on the Internet. We will generate it using openssl. The below command: ``` openssl req --nodes -new -x509 -days 3650 -extensions v3_ca -keyout cacert.private.pem -out cacert.pem -config /etc/ssl/openssl.cnf ``` Will prompt you to fill out the fields of the certificate. None of them matter, and they can all be filled out to anything you want or left blank, except you should fill out "Common Name" with something unique. After the command runs, you will be left with two files in your current directory, cacert.pem and cacert.private.pem. The .pem file is the Root CA, which you will have to install on the target device. The .private.pem is going to be used in the next step to sign a certificate with this CA. ### Generate Signed Certificate Now that we generated the Root CA, we need to generate a certificate that is signed by it. The target device will be able to use the Root CA to cryptographically verifiy that a presented certificate is trustworthy. The below command generates a self-signed certificate, which is not signed by any certificate authority. Once it's created, it will be signed by later steps. ``` openssl req -x509 -newkey rsa:4096 -keyout mycert.private.pem -out mycert.pem -days 365 --nodes ``` It will also prompt you for fields similar to when we created the Root CA. Again, they can all be anything, **except** the "Common Name (e.g. server FQDN or YOUR name)" must be set to ```twitter.com```, or the target server that you're intercepting. Use a full domain here, for subdomains or additional domains, we will use a subject alternative name file in the next few steps. Next, we're going to move around the files a bit into a structure that plays nicer with openssl's ca command. There's probably a better way to do this, but after seeing this excerpt from the ```ca``` man page: "The ca command is quirky and at times downright unfriendly.", I'm giving up on that, and going with their structure. First, create a file named ```alt.txt``` in the current directory, containing the following: ``` [v3_req] subjectAltName = @alt_names [alt_names] DNS.1 = twitter.com DNS.2 = *.twitter.com ``` Where the ```DNS.1```, ```DNS.2```, and so on values are replaced with whatever domain/wildcard domains you want to spoof with your HTTPS certificate. Then run the following commands to actually generate the certificate: ``` mkdir -p demoCA/newcerts touch demoCA/index.txt echo '01' > demoCA/serial openssl ca -policy policy_anything -keyfile cacert.private.pem -cert cacert.pem -ss_cert mycert.pem -out mycert.signed.pem -extensions v3_req -extfile alt.txt ``` When it asks you to sign the certificate and commit the change, say yes and yes. The end result will be ```mycert.signed.pem``` in the current directory. This is the next certificate in the chain of trust, and it should be presented to the client by our nginx server alongside a copy of the Root CA. For this guide, we'll copy these files (private and signed chain) into a new folder, ```/etc/nginx/mitm```: ``` mkdir /etc/nginx/mitm cp mycert.private.pem mycert.signed.pem /etc/nginx/mitm ``` ### Server Setup The server certificate is what our MITM server will present to the client instead of the remote server's. It must be signed by the above generated root ca, so that when the client sees it, it wil trust it from having the root CA installed. Open the ```/etc/nginx/nginx.conf``` file, and put the following contents inside of the ```http { ... }``` block: ``` server { listen 80; server_name twitter.com; return 302 https://nitter.net$request_uri; } server { listen 443 ssl http2; server_name twitter.com; ssl_certificate /etc/nginx/mitm/mycert.signed.pem; ssl_certificate_key /etc/nginx/mitm/mycert.private.pem; return 302 https://nitter.net$request_uri; } ``` In this case, the server_name we are pretending to be is ```twitter.com```, and we are going to handle all requests by redirecting the incoming `request_uri` (URL path) to `nitter.net`. In this case, we are passing it along to another website, but the ```location``` block could also be used to `proxy_pass` it to a local server such as ```http://localhost:8080```. ## Testing it Out Up until this point, we've created a custom root ca certificate, created the nginx configuration file that uses our custom certificate to pass along the traffic, and should have already a local DNS server that forwards requests for the target domain to us. To verifiy everything is working, let's bring up the nginx server: ``` service nginx start ``` Hopefully it starts without any errors. If it does encounter errors, use ```service nginx status``` to see what they are. It would likely be a syntax issue. We can test the DNS server as well, using the ```host``` command: ``` host twitter.com 192.168.0.123 ``` Should report: "twitter.com has address 192.168.0.123", which demonstrates it's resolving to our server's internal IP rather than Twitter's. Now, if you set your computer's DNS server to ```127.0.0.1``` in your network settings, and try to visit [https://twitter.com](https://twitter.com) in the browser, you should be presented with a security warning:  The target device will reject this as it doesn't recognize the certificate that is being presented by our nginx server for twitter.com (as it shouldn't). If you import the generated ```cacert.pem``` into your browser, however, then the browser will be able to see the presented certificate as trusted. To dismiss this warning, and test our MITM setup, import the Certificate Authority into your Browser or Operating System. This is the ```cacert.pem``` file. For example, in Chromium on Linux, this is managed in settings. If you were successful in importing your custom CA, signing your custom Twitter.com certificate, setting up the DNS server to reroute twitter.com to your machine, and setting up nginx, you should now be redirected to nitter! You can also verify this from the command line: ``` curl https://twitter.com -I ``` Which should return: ``` HTTP/2 302 server: nginx/1.18.0 (Ubuntu) date: Fri, 29 Dec 2023 02:42:59 GMT content-type: text/html content-length: 154 location: https://nitter.net/ ``` If the certificate wasn't trusted, you will receive the following response instead: ``` curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: https://curl.se/docs/sslcerts.html curl failed to verify the legitimacy of the server and therefore could not establish a secure connection to it. To learn more about this situation and how to fix it, please visit the web page mentioned above. ``` ### Additional information On some operating systems, you may not be able to import the .pem directly, if this is the case, use the following command: ``` openssl x509 -in cacert.pem -out cacert.der -outform DER ``` And then import `cacert.der` in Keychain or the equivalent. Depending on your browser and security systems, you may also just be able to trust it directly in the browser. On macOS, the GUI in Keychain Access looks as follows:  And upon closing the dialogue after choosing "Always Trust", it should prompt you for your password.