This is a proof of concept to intercept very large amount of datas posing as a local MITM using a root proxy certificate (here generated by Proxyman, but that can be achieved with Charles Proxy or Burp similarly), which sends the intercepted datas to a Node.js Express server, itself communicating with a MongoDB database, it acts as a middleware between the Proxyman scripting tool and a local MongoDB database.
A good example application is to intercept and store all JSON documents, or graphQL queries, to a local database for further analysis. It can be useful for testing and debugging purposes or to rebuilt a graph from scattered request datas.
Note that this will not work on some website, for a variety of reasons such as SSL-pinning (when the website has been configured to trust only a given certificate instead of a list of trusted root certificate authorities (CAs) in the browser, in which our root proxy has been added). It will not work on most mobile apps, beaucause similarly, they are not using the system's root certificate authorities, but instead include the SSL certificate as part of the application bundle.
Keep in mind that this is a proof of concept and for educational purposes only. It is not meant to be used in production. Use this in accordance with local laws and regulations.
One way to implement SSL pinning when the client is a web browser is to include the SSL certificate as part of the application code. This is known as certificate pinning or static pinning as explained above. The web application can include the SSL certificate in the application code, and the application can use this certificate to verify the server's identity. This approach allows the web application to bypass the browser's trust store and to trust only the certificate that is included in the application code.
Another way to implement SSL pinning when the client is a web browser is to use dynamic pinning. This approach, also known as a Certificate and Public Key Pinning typically takes place during the SSL/TLS Handshake, involves the web application dynamically obtaining the SSL certificate from the server and then comparing the certificate to one previously obtained and stored locally on in the browser. If the certificate obtained from the server matches the previously obtained certificate, the web application proceeds with the SSL/TLS handshake. Otherwise, the web application terminates the connection.
Static pinning is generally considered to be less flexible and more difficult to update than dynamic pinning, albeit more secure as there is no need to store the certificate locally, it comes with the application bundle.
Certificate Pinning Extension for HTTP and Public Key Pinning Extension for HTTP (HPKP) are obsolete and should not be used.
Similar certificate-level encryption can be achieve with a custom implementation using the standard WebCrypto API primitives. This can only be achieved after an initial secure handshake with the server using HTTPS (which can still be intercepted by the proxy), and then the client can use the server's public key to encrypt the data. This is not the case of SSL-pinning, which is done as an initial handshake (hence secure regarding proxy interception). This approach is low-level, quite complex, and should be reserved for security experts. It is not recommended for most developers, remember erroneous security mechanism implementations is the most common cause of cybersecurity vulnerabilities.
As a side node, it is worth mentioning that SSL-pinning, in addition to securing the connection, allow for symetric encryption of the data, which is more efficient than asymmetric encryption. Symetric encryption means that the same key is used to encrypt and decrypt the data, whereas in asymmetric encryption, the data is encrypted with a public key and decrypted with a private key.
You can learn more about SSL pinning in the browser here.
Clone this repository, lock the dependencies using NPM, transpile the MongoDB driver, bundle the code and dependencies using Browserify (see setup.sh) and add proxyman.js to the Proxyman script directory.
setup.sh is a shell script that sets up the environment for the Node.js server application and the Proxyman script. It first verifies that MongoDB is running and creates the graphDB database and nodes collection. Then, it installs the libraries, transpiles the MongoDB driver, bundles the code and dependencies using Browserify.
Proxyman.js is a script that runs on the Proxyman app. It sends an HTTP POST request to the Node.js server application and logs the status code, body, and headers of the response for debugging purposes, you should remove this for performance reasons once the workflow is working.
main.ts is the main middleware for the Node.js server application. It uses the Express library to handle HTTP requests on one side and the MongoDB driver to connect with the MongoDB database on the other one. The middleware listens for HTTP POST requests made at the /api/items endpoint, and once received, inserts the captured documents in the MongoDB collection items. The middleware listens on port 3000 and returns the result of the MongoDB insertion as a response to the client.
-
Make sure that MongoDB is running and create the 'graphDB' database and 'nodes' collection (check it is actually listening with
netstat -an | grep 27017
orlsof -i :27017
, and yes, lsof is the best at everything) -
Install and/or update the dependencies using NPM
-
Verify that the MongoDB driver is transpiled
-
Code and dependencies are bundled using Browserify
-
Express server is running and listening on port 3000 (again, check it is actually listening with
netstat -an | grep 3000
orlsof -i :3000
) -
Run the Proxyman script to send HTTP POST requests to the server (check Proxyman scripting tool console for debugging)