Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ImpersonatingMitmManager - Bypass MITM depending on domain #733

Open
ScottDennison opened this issue Mar 7, 2018 · 4 comments
Open

ImpersonatingMitmManager - Bypass MITM depending on domain #733

ScottDennison opened this issue Mar 7, 2018 · 4 comments

Comments

@ScottDennison
Copy link

ScottDennison commented Mar 7, 2018

Is it possible to make ImpersonatingMitmManager (when combined with LittleProxy) perform a direct passthrough without certificate impersonation, if upon a CONNECT, the domain does not match one of a series of whitelist regular expressions?

I need to have the proxy accepting all browser traffic, but I only want to run filters for a small percentage of said traffic, MITM needs to be selective so that certificate pinned applications do not receive a generated certificate and therefore break. An example of this is DropBox - when the Windows system proxy is set to the proxy, Dropbox refuses to sync.

Is this possible?
Looking over the code, it looks like clientSslEngineFor always calls getHostnameImpersonatingSslContext, so there is not a current way to do this, but I might have missed something.

The company I work for uses a home-rolled authentication protocol similar to HAWK when talking to microservices. This proves to be a pain when testing those microservices, so I wrote a Fiddler plugin that automatically adds the required authentication headers to any outgoing requests that look like they are for an internal company domain. This allows for standard REST requests to be made in the browser / rest client and for them to be transparent signed. However, we are now looking to move away from requiring Fiddler.

@NickEm
Copy link

NickEm commented Mar 7, 2018

If I get you right, you want your proxy to work for all domains except whitelisted. I bet that can be solved on higher level

    final Set<String> whitelistDomains = new HashSet<>(Arrays.asList("google.co.uk", "github.com"));
    HttpProxyServer server = DefaultHttpProxyServer.bootstrap()
            .withPort(8080)
            .withFiltersSource(new HttpFiltersSourceAdapter() {
                public HttpFilters filterRequest(HttpRequest originalRequest, ChannelHandlerContext ctx) {
                    String uri = originalRequest.uri();
                    String domain = null;
                    try {
                        URL url = new URL(uri);
                        domain = url.getHost();
                    } catch (MalformedURLException e) {
                        // TODO: implement your custom logic here
                    }
                    if (whitelistDomains.contains(domain)) {
                        // Just skip filtering
                        return null;
                    } else {
                        return new HttpFiltersAdapter(originalRequest) {
                            @Override
                            public HttpResponse clientToProxyRequest(HttpObject httpObject) {
                                // TODO: implement your filtering here
                                return null;
                            }

                            @Override
                            public HttpObject serverToProxyResponse(HttpObject httpObject) {
                                // TODO: implement your filtering here
                                return httpObject;
                            }
                        };
                    }
                }
            })
            .start();

@ScottDennison
Copy link
Author

ScottDennison commented Mar 7, 2018

@NickEm

Thanks for posting that.
It is the opposite way around (only filter if in the list), but that is just a case of reversing the if.
However, unfortunately, this is not what I am looking for.

Even if you don't filter (return null) such a request, if it is HTTPS, the MITM manager will have already generated a self-signed certificate and will have used that to impersonate the server. This breaks applications that use certificate pinning (Which I incorrectly referred to as HSTS in my first post, and have since edited).

Similar to FiddlerCore's x-no-decrypt option, I don't even want certificate impersonation to occur if the request doesn't match the whitelist. Instead, the original non-mitm certificate should be returned, and subsequent requests that are encrypted inside the resulting CONNECT tunnel should be passed through as-is without decryption or encryption.

P.S: Given this is more of a discussion than an issue (yet, at least (given I suspect it will end up becoming a feature request)), should I move this to stackoverflow?

@NickEm
Copy link

NickEm commented Mar 7, 2018

@ScottDennison
All right, now I got it. Unfortunately, no answer so far, deeper investigation is required.

@ScottDennison
Copy link
Author

ScottDennison commented Mar 8, 2018

A bit more digging revealed that this isn't easily fixable inside browsermob-proxy mitm, and instead needs a change to LittleProxy. See my pull request at adamfisk/LittleProxy#406

Note that pull request adamfisk/LittleProxy#402 (not mine) of LittleProxy upgrades LittleProxy to java 8. If that goes in, then this project would also then need upgrading.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants