From cd00730c0b12e119f4debf0b3cd6163cc031adfe Mon Sep 17 00:00:00 2001 From: cr0hn Date: Fri, 26 Feb 2016 12:48:02 +0100 Subject: [PATCH] fix: in codding errors when try to parse remote web page fix: log levels add: improved dump deserization of data when it is received from Redis --- enteletaor_lib/modules/redis/cmd_actions.py | 2 +- enteletaor_lib/modules/redis/redis_cache.py | 11 +- .../modules/redis/redis_disconnect.py | 2 +- enteletaor_lib/modules/redis/redis_dump.py | 127 +++++++++++++++++- 4 files changed, 129 insertions(+), 13 deletions(-) diff --git a/enteletaor_lib/modules/redis/cmd_actions.py b/enteletaor_lib/modules/redis/cmd_actions.py index b36e437..cfc2335 100644 --- a/enteletaor_lib/modules/redis/cmd_actions.py +++ b/enteletaor_lib/modules/redis/cmd_actions.py @@ -11,7 +11,7 @@ def parser_redis_dump(parser): Dump all redis database information """ gr = parser.add_argument_group("custom raw dump options") - gr.add_argument("--no-raw", action="store_true", dest="no_raw", default=False, + gr.add_argument("--no-screen", action="store_true", dest="no_screen", default=False, help="do not show displays raw database info into screen") diff --git a/enteletaor_lib/modules/redis/redis_cache.py b/enteletaor_lib/modules/redis/redis_cache.py index 76ceccc..d50a180 100644 --- a/enteletaor_lib/modules/redis/redis_cache.py +++ b/enteletaor_lib/modules/redis/redis_cache.py @@ -102,7 +102,10 @@ def handle_html(config, content): insert_point.addnext(payload) # Set results - results = bytes(etree.tostring(doc_root)) + tmp_results = etree.tostring(doc_root, method="html", pretty_print=True, encoding=doc_root.docinfo.encoding) + + # Codding filters + results = tmp_results.decode(errors="replace").replace("\\u000a", "\n") break @@ -137,10 +140,10 @@ def action_redis_cache_poison(config): log.error("Looking for caches in '%s'..." % config.target) for x in cache_keys: - log.warning(" - Possible cache found in key: %s" % str(x)) + log.error(" - Possible cache found in key: %s" % str(x)) if not cache_keys: - log.warning(" - No caches found") + log.error(" - No caches found") # Stop return @@ -177,7 +180,7 @@ def action_redis_cache_poison(config): # Injection was successful? if modified is None: - log.warning(" - Can't modify content: ensure that content is HTML") + log.error(" - Can't modify content: ensure that content is HTML") continue # Set injection into server diff --git a/enteletaor_lib/modules/redis/redis_disconnect.py b/enteletaor_lib/modules/redis/redis_disconnect.py index 58de945..6b11f8d 100644 --- a/enteletaor_lib/modules/redis/redis_disconnect.py +++ b/enteletaor_lib/modules/redis/redis_disconnect.py @@ -40,4 +40,4 @@ def action_redis_server_disconnect(config): log.error(" - Disconnected client '%s'" % _c) except KeyError: - log.warning("Client '%s' doesn't appear to be connected to server" % config.client) + log.error("Client '%s' doesn't appear to be connected to server" % config.client) diff --git a/enteletaor_lib/modules/redis/redis_dump.py b/enteletaor_lib/modules/redis/redis_dump.py index d912e5f..e55426d 100644 --- a/enteletaor_lib/modules/redis/redis_dump.py +++ b/enteletaor_lib/modules/redis/redis_dump.py @@ -1,7 +1,13 @@ # -*- coding: utf-8 -*- +import six +import json import redis +import base64 import logging +import binascii + +from six.moves.cPickle import loads log = logging.getLogger() @@ -12,13 +18,13 @@ def dump_keys(con): for key in con.keys('*'): key_type = con.type(key).lower() val = None - if key_type == b"kv": + if key_type in (b"kv", b"string"): val = con.get(key) - if key_type == b"hash": + if key_type in (b"hash", b"unacked", b"unacked_index"): val = con.hgetall(key) if key_type == b"zet": val = con.zrange(key, 0, -1) - if key_type == b"set": + if key_type in (b"set", b"list"): val = con.mget(key) if val is not None: @@ -26,7 +32,107 @@ def dump_keys(con): if val[0] is None: continue - yield val + yield key, val + + +# -------------------------------------------------------------------------- +# Human parsers +# -------------------------------------------------------------------------- +def decode_object(key, val, ident=5): + + if isinstance(val, dict): + + log.error(' "%s":' % key) + log.error(" {") + _decode_object(val, ident) + log.error(" }") + else: + log.error(' "%s": "%s"' % (key, val)) + + +# ---------------------------------------------------------------------- +def _decode_object(val, ident=5): + """ + Decode recursively string + """ + _new_ident = ident + 1 + + for k, v in six.iteritems(val): + # convert value to original type -> JSON + try: + _transformed_info = json.loads(v.decode("utf-8")) + except (binascii.Error, AttributeError): + _transformed_info = v + + # -------------------------------------------------------------------------- + # Try to display in "human" format + # -------------------------------------------------------------------------- + if isinstance(_transformed_info, list): + + log.error('%s"%s":' % (" " * ident, k)) + + for x in _transformed_info: + if isinstance(x, dict): + # Open data + log.error("%s{" % (" " * _new_ident)) + + _decode_object(x, _new_ident + 2) + + log.error("%s}" % (" " * _new_ident)) + + else: + log.error('%s"%s"' % ((" " * ident), x)) + + # Dict handler + elif isinstance(_transformed_info, dict): + log.error('%s"%s":' % ((" " * ident), k)) + + log.error("%s{" % (" " * _new_ident)) + + _decode_object(v, _new_ident + 2) + + log.error("%s}" % (" " * _new_ident)) + + # Basic type as value + else: + + try: + use_obj = _transformed_info.encode() + except (TypeError, AttributeError, binascii.Error): + use_obj = _transformed_info + + # Is Pickle encoded? + try: + _pickle_decoded = loads(use_obj) + + # Is pickled + log.error('%s"%s":' % ((" " * ident), k)) + + log.error("%s{" % (" " * _new_ident)) + + _decode_object(_pickle_decoded, _new_ident + 2) + + log.error("%s}" % (" " * _new_ident)) + + except Exception: + + # Try again decoding in base64 + try: + _b64_decoded = base64.decodebytes(use_obj) + + # Is pickled + log.error('%s"%s":' % ((" " * ident), k)) + + log.error("%s{" % (" " * _new_ident)) + + _decode_object(loads(_b64_decoded), _new_ident + 2) + + log.error("%s}" % (" " * _new_ident)) + + except Exception: + + # Transform is not possible -> plain string + log.error('%s"%s": "%s"' % ((" " * ident), k, use_obj)) # ---------------------------------------------------------------------- @@ -44,15 +150,22 @@ def action_redis_dump(config): if config.export_results: export_file = open(config.export_results, "w") - for val in dump_keys(con): + i = 0 + for i, t_val in enumerate(dump_keys(con)): + key = t_val[0] + val = t_val[1] + # Display results? - if config.no_raw is False: - log.warning(val) + if config.no_screen is False: + decode_object(key, val) # Dump to file? if export_file is not None: export_file.write(str(val)) + if i == 0: + log.error(" - No information to dump in database") + # Close file descriptor if export_file is not None: export_file.close()