Responder icon indicating copy to clipboard operation
Responder copied to clipboard

DontRespondTo fails to blacklist target IPs (solution included).

Open Cat0x00 opened this issue 6 months ago • 1 comments

Hi @lgandx . Absolutely amazing tool. Want to help with improving it.

Context: OS - Raspberry Pi with Kali Linux (using responder from the original Kali repo). Version - Responder 3.1.3.0 Network interface - eth0, has IPv4 and IPv6 addresses.

There are two issues with the DontRespondTo config option which fails to do what it needs to do.

1. IPv4 IPs in DontRespondTo are not blacklisted

The problem is with IPv4 and IPv6 interfaces. During poisoning i noticed that the target IPv4 comes in like '::ffff:10.0.0.1' and for magic reasons i could not figure out WHY the replace in MDNS.py (https://github.com/lgandx/Responder/blob/master/poisoners/MDNS.py#L63 and maybe elsewhere) does not properly stirp the "::ffff" part which later fails in blacklist validation. I did extensive debugging and traced that "if (not Request_Name) or (RespondToThisHost(self.client_address[0].replace("::ffff:",""), Request_Name) is not True):" does not replace the "ffff" as i was outputing the incoming ClientIp in RespondToThisHost() and saw that it comes in with the "ffff"s.

So what I did was I modified the RespondToThisIP() function in utils.py to explicitly replace the prefix again:

def RespondToThisIP(ClientIp):
	ClientIp = ClientIp.replace("::ffff:","")
	if ClientIp.startswith('127.0.0.'):
		return False
	elif settings.Config.AutoIgnore and ClientIp in settings.Config.AutoIgnoreList:
		print(color('[*]', 3, 1), 'Received request from auto-ignored client %s, not answering.' % ClientIp)
		return False
	elif settings.Config.RespondTo and ClientIp not in settings.Config.RespondTo:
		return False
	elif ClientIp in settings.Config.RespondTo or settings.Config.RespondTo == []:
		if ClientIp not in settings.Config.DontRespondTo:
			return True
	return False

This way I was getting consistent and working '::ffff:10.0.0.1' prefix removal before the check (if ClientIp not in settings.Config.DontRespondTo:) which resulted in the expected behavior.

2. IPv6 blacklist support

Currently if we try to blacklist IPv6 via DontRespondTo we get an error:

Traceback (most recent call last):
  File "/usr/share/responder/./Responder.py", line 62, in <module>
    settings.Config.ExpandIPRanges()
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/share/responder/settings.py", line 67, in ExpandIPRanges
    self.DontRespondTo = expand_ranges(self.DontRespondTo)
                         ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/usr/share/responder/settings.py", line 53, in expand_ranges
    x[i] = x[i+1] = int(byte)
                    ~~~^^^^^^
ValueError: invalid literal for int() with base 10: 'FE80::1111:AAAA:2222:333'

This is because the tool does not have IPv6 ip address parsing via expand_ranges() function.

With some AI help I updated the code to include modified expand_ranges() (settings.py) which allows specifyin IPv6 addresses in the DontRespondTo config option.

def expand_ranges(lst):	
	ret = []
	for l in lst:
		if ':' in l: #For IPv6 addresses
			# Check if it's actually an IPv6 address (not just an IPv4 with port)
			if l.count(':') >= 2:  # IPv6 has at least 2 colons
				while l.count(':') < 7: 
					pos = l.find('::')
					if pos == -1:
						break  # No :: found, can't expand further
					l = l[:pos] + ':' + l[pos:]
				tab = l.split(':')
				x = {}
				i = 0
				for byte in tab:
					if byte == '':
						byte = '0'
					if '-' not in byte:
						x[i] = x[i+1] = int(byte, 16)  # Use base 16 for hex
					else:
						b = byte.split('-')
						x[i] = int(b[0], 16)	# Use base 16 for hex
						x[i+1] = int(b[1], 16)  # Use base 16 for hex
					i += 2
				for a in range(x[0], x[1]+1):
					for b in range(x[2], x[3]+1):
						for c in range(x[4], x[5]+1):
							for d in range(x[6], x[7]+1):
								for e in range(x[8], x[9]+1):
									for f in range(x[10], x[11]+1):
										for g in range(x[12], x[13]+1):
											for h in range(x[14], x[15]+1):
												xaddr = ('%x:%x:%x:%x:%x:%x:%x:%x' % (a, b, c, d, e, f, g, h))
												xaddr = re.sub('(^|:)0{1,4}', ':', xaddr, count = 7)
												xaddr = re.sub(':{3,7}', '::', xaddr, count = 7)
												ret.append(xaddr)
			else:
				# It's an IPv4 address with port, treat as single IP
				ret.append(l)
		else:
			# IPv4 address processing (existing code)
			tab = l.split('.')
			x = {}
			i = 0
			for byte in tab:
				if '-' not in byte:
					x[i] = x[i+1] = int(byte)  # Base 10 for IPv4
				else:
					b = byte.split('-')
					x[i] = int(b[0])
					x[i+1] = int(b[1])
				i += 2
			for a in range(x[0], x[1]+1):
				for b in range(x[2], x[3]+1):
					for c in range(x[4], x[5]+1):
						for d in range(x[6], x[7]+1):
							ret.append('%d.%d.%d.%d' % (a, b, c, d))
	return ret

I would be happy if this gets merged into the next release since it happens too often that i need to blacklist noisy IPs but fail due to the caveats of the tool.

Cat0x00 avatar Jul 01 '25 10:07 Cat0x00

Hi,

Thanks for the detailed issue, if this was not fixed in the latest version 3.1.6.0 please submit a PR and i will review it.

Thanks!

lgandx avatar Jul 06 '25 22:07 lgandx