ソースを参照

Static redirect script detection

RichardG867 5 年 前
コミット
59da2bf27d
1 ファイル変更28 行追加2 行削除
  1. 28 2
      waybackproxy.py

+ 28 - 2
waybackproxy.py

@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-import base64, re, socket, socketserver, sys, threading, urllib.request, urllib.error, urllib.parse, urllib.parse
+import base64, re, socket, socketserver, sys, threading, urllib.request, urllib.error, urllib.parse
 from config import *
 
 class ThreadingTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
@@ -91,6 +91,16 @@ class Handler(socketserver.BaseRequestHandler):
 				conn = urllib.request.urlopen('http://web.archive.org/web/{0}/{1}'.format(DATE, request_url))
 		except urllib.error.HTTPError as e:
 			# an error has been found
+
+			# 403 or 404 => heuristically determine the static URL for some redirect scripts
+			if e.code in (403, 404):
+				match = re.search('''(?:\?|&)(?:target|trg|dest(?:ination)?|to)(?:url)?=(http[^&]+)''', request_url, re.IGNORECASE)
+				if match:
+					# we found it
+					new_url = urllib.parse.unquote_plus(match.group(1))
+					_print('[r]', new_url)
+					return self.redirect_page(http_version, new_url)
+
 			_print('[!] {0} {1}'.format(e.code, e.reason))
 			return self.error_page(http_version, e.code, e.reason)
 		
@@ -217,6 +227,20 @@ class Handler(socketserver.BaseRequestHandler):
 		# send error page and stop
 		self.request.sendall('{0} {1} {2}\r\nContent-Type: text/html\r\nContent-Length: {3}\r\n\r\n{4}'.format(http_version, code, reason, len(errorpage), errorpage).encode('utf8', 'ignore'))
 		self.request.close()
+
+	def redirect_page(self, http_version, target, code=302):
+		"""Generate a redirect page."""
+
+		# make redirect page
+		redirectpage  = '<html><head><title>Redirect</title><meta http-equiv="refresh" content="0;url='
+		redirectpage += target
+		redirectpage += '"></head><body><p>If you are not redirected, <a href="'
+		redirectpage += target
+		redirectpage += '">click here</a>.</p></body></html>'
+
+		# send redirect page and stop
+		self.request.sendall('{0} {1} Found\r\nLocation: {2}\r\nContent-Type: text/html\r\nContent-Length: {3}\r\n\r\n'.format(http_version, code, target, len(redirectpage), redirectpage).encode('utf8', 'ignore'))
+		self.request.close()
 	
 	def handle_settings(self, query):
 		"""Generate the settings page."""
@@ -252,7 +276,9 @@ class Handler(socketserver.BaseRequestHandler):
 		return 'WaybackProxy on {0}'.format(socket.gethostname())
 
 print_lock = threading.Lock()
-def _print(s, linebreak=True):
+def _print(*args, linebreak=True):
+	"""Logging function."""
+	s = ' '.join(args)
 	print_lock.acquire()
 	sys.stdout.write(linebreak and (s + '\n') or s)
 	sys.stdout.flush()