From 64b14720c14dce7dd8cc13061cabd843ef0482be Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Fri, 26 Jan 2018 18:10:38 -0600 Subject: [PATCH] fixed broken dns rebinding mitigation and secured peer adding --- onionr/api.py | 2 +- onionr/onionrutils.py | 35 +++++++++++++++++++++++++++-------- onionr/tests.py | 2 +- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/onionr/api.py b/onionr/api.py index bc3c069e..091093f7 100755 --- a/onionr/api.py +++ b/onionr/api.py @@ -176,7 +176,7 @@ class API: # Validate host header, to protect against DNS rebinding attacks host = self.host if hostType == 'private': - if not request.host.startswith('127'): + if not request.host.startswith('127') and not self._utils.checkIsIP(request.host): abort(403) elif hostType == 'public': if not request.host.endswith('onion') and not request.host.endswith('i2p'): diff --git a/onionr/onionrutils.py b/onionr/onionrutils.py index d846a6f9..30216770 100644 --- a/onionr/onionrutils.py +++ b/onionr/onionrutils.py @@ -69,6 +69,13 @@ class OnionrUtils: finally: sock.close() return retVal + def checkIsIP(self, ip): + try: + socket.inet_aton(ip) + except: + return False + else: + return True def exportMyPubkey(self): '''Export our PGP key if it exists''' if not os.path.exists(self.fingerprintFile): @@ -107,27 +114,39 @@ class OnionrUtils: idLength = len(id) retVal = True idNoDomain = '' - #if idLength != 60 and idLength != 22 and idLength != 62: + peerType = '' + # i2p b32 addresses are 60 characters long (including .b32.i2p) if idLength == 60: - if not id.endsWith('.b32.i2p'): + peerType = 'i2p' + if not id.endswith('.b32.i2p'): retVal = False else: idNoDomain = id.split('.b32.i2p')[0] + # Onion v2's are 22 (including .onion), v3's are 62 with .onion elif idLength == 22 or idLength == 62: - if not id.endsWith('.onion'): + peerType = 'onion' + if not id.endswith('.onion'): retVal = False else: idNoDomain = id.split('.onion')[0] else: retVal = False if retVal: - if id.endsWith('.onion'): + if peerType == 'i2p': try: - int(idNoDomain, 16) - except ValueError: + id.split('.b32.i2p')[2] + except: + pass + else: retVal = False - elif id.endsWith('.b32.i2p'): - if not idNoDomain.isalnum(): + elif peerType == 'onion': + try: + id.split('.onion')[2] + except: + pass + else: retVal = False + if not idNoDomain.isalnum(): + retVal = False return retVal diff --git a/onionr/tests.py b/onionr/tests.py index 93c5ba38..df2f1727 100755 --- a/onionr/tests.py +++ b/onionr/tests.py @@ -51,7 +51,7 @@ class OnionrTests(unittest.TestCase): myCore = core.Core() if not os.path.exists('data/peers.db'): myCore.createPeerDB() - if myCore.addPeer('test'): + if myCore.addPeer('facebookcorewwwi.onion') and not myCore.addPeer('invalidpeer.onion'): self.assertTrue(True) else: self.assertTrue(False)