Browse Source

Fix header replacement

pull/58/head
Kristijan Mitrovic 4 years ago
parent
commit
54c6b5cb0a
1 changed files with 47 additions and 22 deletions
  1. +47
    -22
      bubble-server/src/main/resources/packer/roles/mitmproxy/files/bubble_api.py

+ 47
- 22
bubble-server/src/main/resources/packer/roles/mitmproxy/files/bubble_api.py View File

@@ -450,7 +450,7 @@ def original_flex_ip(client_addr, fqdns):
return None return None




def _replace_in_headers(headers: nheaders.Headers, pattern: str, replacement: str):
def _replace_in_headers(headers: nheaders.Headers, modifiers_dict: dict) -> int:
""" """
Taken from original mitmproxy's Header class implementation with sligh change to allow replacement with empty string Taken from original mitmproxy's Header class implementation with sligh change to allow replacement with empty string
(resulting with actual removal/skip of the header line). (resulting with actual removal/skip of the header line).
@@ -461,26 +461,34 @@ def _replace_in_headers(headers: nheaders.Headers, pattern: str, replacement: st
Returns: Returns:
The number of replacements made. The number of replacements made.
""" """
pattern = re.compile(strutils.escaped_str_to_bytes(pattern))
replacement = strutils.escaped_str_to_bytes(replacement)
repl_count = 0 repl_count = 0
fields = [] fields = []


for name, value in headers.fields: for name, value in headers.fields:
line, n = pattern.subn(replacement, name + b": " + value)

line = name + b": " + value
inner_repl_count = 0
for pattern, replacement in modifiers_dict.items():
line, n = pattern.subn(replacement, line)
inner_repl_count += n
if len(line) == 0:
# No need to go though other patterns for this line
break


if len(line) == 0: if len(line) == 0:
# Skip/remove this header line and go with the next one:
continue
# Skip (remove) this header line in this case
break


try:
name, value = line.split(b": ", 1)
except ValueError:
# We get a ValueError if the replacement removed the ": "
# There's not much we can do about this, so we just keep the header as-is.
pass
else:
repl_count += n
if inner_repl_count > 0:
# only in case when there were some replacements:
try:
name, value = line.split(b": ", 1)
except ValueError:
# We get a ValueError if the replacement removed the ": "
# There's not much we can do about this, so we just keep the header as-is.
pass
else:
repl_count += inner_repl_count


fields.append((name, value)) fields.append((name, value))


@@ -488,21 +496,25 @@ def _replace_in_headers(headers: nheaders.Headers, pattern: str, replacement: st
return repl_count return repl_count




def response_header_modify(flow):
def response_header_modify(flow) -> int:
if flow.response is None: if flow.response is None:
return None return None
return _header_modify(flow.client_conn.address[0], flow.server_conn.address[0], flow.response.headers)

ctx = {'fqdn': flow.server_conn.address[0]}
return _header_modify(flow.client_conn.address[0], ctx, flow.response.headers)




def _header_modify(client_addr: str, server_addr: str, headers: nheaders.Headers):
def _header_modify(client_addr: str, ctx: dict, headers: nheaders.Headers) -> int:
modifiers_set = 'responseHeaderModifierLists~' + client_addr + '~UNION' modifiers_set = 'responseHeaderModifierLists~' + client_addr + '~UNION'
modifiers = REDIS.smembers(modifiers_set) modifiers = REDIS.smembers(modifiers_set)


repl_count = 0 repl_count = 0
if modifiers: if modifiers:
modifiers_dict = {}
for modifier in modifiers: for modifier in modifiers:
modifier_config = _extract_modifier_config(modifier, server_addr)
repl_count += _replace_in_headers(headers, modifier_config['regex'], modifier_config['replacement'])
regex, replacement = _extract_modifier_config(modifier, ctx)
modifiers_dict[regex] = replacement
repl_count += _replace_in_headers(headers, modifiers_dict)


if bubble_log.isEnabledFor(DEBUG): if bubble_log.isEnabledFor(DEBUG):
bubble_log.debug('_header_modify: replacing headers - replacements count: ' + repl_count) bubble_log.debug('_header_modify: replacing headers - replacements count: ' + repl_count)
@@ -510,9 +522,22 @@ def _header_modify(client_addr: str, server_addr: str, headers: nheaders.Headers
return repl_count return repl_count




def _extract_modifier_config(modifier: str, server_addr: str):
modifier.replace('{{fqdn}}', re.escape(server_addr))
return json.loads(modifier)
def _extract_modifier_config(modifier: bytes, ctx: dict) -> tuple:
modifier_obj = json.loads(modifier)

regex = _replace_modifier_values(modifier_obj['regex'], ctx)
replacement = _replace_modifier_values(modifier_obj['replacement'], ctx)

regex = re.compile(strutils.escaped_str_to_bytes(regex))
replacement = strutils.escaped_str_to_bytes(replacement)

return regex, replacement


def _replace_modifier_values(s: str, ctx: dict) -> str:
# no loop over ctx currently to speed up as there's just 1 variable inside
s = s.replace('{{fqdn}}', re.escape(ctx['fqdn']))
return s




def health_check_response(flow): def health_check_response(flow):


Loading…
Cancel
Save