The main Bubble source repository. Contains the Bubble API server, the web UI, documentation and utilities. https://getbubblenow.com
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

91 行
3.4 KiB

  1. """
  2. This script makes it possible to use mitmproxy in scenarios where IP spoofing
  3. has been used to redirect connections to mitmproxy. The way this works is that
  4. we rely on either the TLS Server Name Indication (SNI) or the Host header of the
  5. HTTP request. Of course, this is not foolproof - if an HTTPS connection comes
  6. without SNI, we don't know the actual target and cannot construct a certificate
  7. that looks valid. Similarly, if there's no Host header or a spoofed Host header,
  8. we're out of luck as well. Using transparent mode is the better option most of
  9. the time.
  10. Usage:
  11. mitmproxy
  12. -p 443
  13. -s dns_spoofing.py
  14. # Used as the target location if neither SNI nor host header are present.
  15. --mode reverse:http://example.com/
  16. # To avoid auto rewriting of host header by the reverse proxy target.
  17. --set keep_host_header
  18. mitmdump
  19. -p 80
  20. --mode reverse:http://localhost:443/
  21. (Setting up a single proxy instance and using iptables to redirect to it
  22. works as well)
  23. """
  24. import json
  25. import re
  26. from bubble_api import bubble_matchers, HEADER_BUBBLE_MATCHERS
  27. from mitmproxy import ctx
  28. # This regex extracts splits the host header into host and port.
  29. # Handles the edge case of IPv6 addresses containing colons.
  30. # https://bugzilla.mozilla.org/show_bug.cgi?id=45891
  31. parse_host_header = re.compile(r"^(?P<host>[^:]+|\[.+\])(?::(?P<port>\d+))?$")
  32. class Rerouter:
  33. @staticmethod
  34. def get_matcher_ids(flow, host):
  35. if host is None:
  36. return None
  37. remote_addr = flow.client_conn.address[0]
  38. host = host.decode('utf-8')
  39. matchers = bubble_matchers(remote_addr, flow, host)
  40. if not matchers:
  41. print("no matchers for remote_addr/host: "+remote_addr+'/'+host)
  42. return None
  43. matcher_ids = []
  44. for m in matchers:
  45. ctx.log.info('get_matcher_ids: checking for match of path='+flow.request.path+' against regex: '+m['regex'])
  46. if re.match(m['regex'], flow.request.path):
  47. ctx.log.info('get_matcher_ids: rule matched, adding rule: '+m['rule'])
  48. matcher_ids.append(m['uuid'])
  49. return matcher_ids
  50. def request(self, flow):
  51. if flow.client_conn.tls_established:
  52. flow.request.scheme = "https"
  53. sni = flow.client_conn.connection.get_servername()
  54. port = 443
  55. else:
  56. flow.request.scheme = "http"
  57. sni = None
  58. port = 80
  59. host_header = flow.request.host_header
  60. m = parse_host_header.match(host_header)
  61. if m:
  62. host_header = m.group("host").strip("[]")
  63. if m.group("port"):
  64. port = int(m.group("port"))
  65. # Determine if this request should be filtered
  66. if sni or host_header:
  67. matchers = self.get_matcher_ids(flow, sni or host_header)
  68. if matchers:
  69. ctx.log.info("dns_spoofing.request: found matchers: " + ' '.join(matchers))
  70. flow.request.headers[HEADER_BUBBLE_MATCHERS] = json.dumps(matchers)
  71. else:
  72. ctx.log.info('dns_spoofing.request: no rules returned, passing thru...')
  73. else:
  74. ctx.log.info('dns_spoofing.request: no sni/host found, not applying rules to path: ' + flow.request.path)
  75. flow.request.host_header = host_header
  76. flow.request.host = sni or host_header
  77. flow.request.port = port
  78. addons = [Rerouter()]