Proof Of Concept Script – Allowing Incoming Server Connections Through An Outbound Client Connection Only (All Through An External Public Server)

#!/usr/bin/python

import os
import random
import select
import socket
import string
import sys
import time

def rndstr(size):
	o = ""
	for x in range(0, size):
		o += random.choice(string.digits + string.ascii_uppercase + string.ascii_lowercase)
	return o

def tryclose(sockobjc):
	try:
		sockobjc.close()
	except:
		pass

def childrwe(socklist):
	buffsize = 1024
	bufflist = ["", ""]
	erroflag = 0; dataflag = 1
	while (erroflag == 0):
		if (dataflag == 0):
			for x in range(0, 2):
				if (bufflist[x]):
					y = ((x + 1) % 2)
					#print("send:",y,"data:",bufflist[x])
					try:
						socklist[y].send(bufflist[x])
						bufflist[x] = ""
					except:
						erroflag = 1
		dataflag = 0
		(readlist, writlist, errolist) = select.select(socklist, [], [], 0.01)
		for x in range(0, 2):
			if (socklist[x] in readlist):
				try:
					databuff = socklist[x].recv(buffsize)
				except:
					databuff = ""
					erroflag = 1
				if (not databuff):
					erroflag = 1
				else:
					bufflist[x] += databuff
					dataflag = 1
	tryclose(socklist[0]); tryclose(socklist[1])
	sys.exit(0)

def main():
	print("%s public [public_port] [private_port] [private_password]" % (sys.argv[0]))
	print("%s private [public_host] [private_port] [private_password] [local_port]" % (sys.argv[0]))
	print("")
	
	buffsize = 1024
	
	if (sys.argv[1] == "public"):
		clieport = int(sys.argv[2])
		servport = int(sys.argv[3])
		password = sys.argv[4]
		
		clieobjc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		clieobjc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		clieobjc.bind(("0.0.0.0", clieport))
		clieobjc.listen(1)
		clielist = []
		
		servobjc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		servobjc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		servobjc.bind(("0.0.0.0", servport))
		servobjc.listen(1)
		servlist = []
		
		childlst = []
		while (1):
			templist = [clieobjc, servobjc]
			for clieitem in clielist:
				if (clieitem[0]):
					templist.append(clieitem[0])
			for servitem in servlist:
				if (servitem[0]):
					templist.append(servitem[0])
			
			(readlist, writlist, errolist) = select.select(templist, [], [])
			
			if (clieobjc in readlist):
				(connobjc, addrobjc) = clieobjc.accept()
				uniqstri = rndstr(16)
				print(int(time.time()),"clie:","connection opened:",addrobjc,"id:",uniqstri)
				clielist.append([connobjc, None, "", addrobjc, uniqstri])
				sentflag = 0
				delelist = []
				for servitem in servlist:
					if (servitem[1] == "control"):
						print(int(time.time()),"serv:","sending notice:",servitem[2],"data:",uniqstri)
						try:
							servitem[0].send(uniqstri)
							sentflag = 1
						except:
							delelist.append(servitem)
					if (sentflag == 1):
						break
				for deleitem in delelist:
					print(int(time.time()),"serv:","connection closed:",deleitem[2])
					tryclose(deleitem[0])
					servlist.remove(deleitem)
			
			elif (servobjc in readlist):
				(connobjc, addrobjc) = servobjc.accept()
				print(int(time.time()),"serv:","connection opened:",addrobjc)
				servlist.append([connobjc, "", addrobjc])
			
			else:
				delelist = []
				for servitem in servlist:
					if (servitem[0] in readlist):
						try:
							databuff = servitem[0].recv(buffsize)
						except:
							delelist.append(servitem)
						if (not databuff):
							delelist.append(servitem)
						else:
							print(int(time.time()),"serv:","recv from:",servitem[2])
							#print(int(time.time()),"serv:","recv from:",servitem[2],"data:",databuff)
							if (databuff.strip() == password):
								print(int(time.time()),"serv:","verified auth:",servitem[2])
								servitem[1] = "control"
							else:
								for clieitem in clielist:
									if (databuff.strip() == clieitem[4]):
										print(int(time.time()),"serv:","est. middle:",clieitem[3],"*----",clieitem[4],"----*",servitem[2])
										clieitem[1] = servitem[0]
				for deleitem in delelist:
					print(int(time.time()),"serv:","connection closed:",deleitem[2])
					tryclose(deleitem[0])
					servlist.remove(deleitem)
				
				delelist = []
				for clieitem in clielist:
					if (clieitem[0] in readlist):
						try:
							databuff = clieitem[0].recv(buffsize)
						except:
							delelist.append(clieitem)
						if (not databuff):
							delelist.append(clieitem)
						else:
							print(int(time.time()),"clie:","recv from:",clieitem[3],"id:",clieitem[4])
							#print(int(time.time()),"clie:","recv from:",clieitem[3],"id:",clieitem[4],"data:",databuff)
							clieitem[2] += databuff
				for deleitem in delelist:
					print(int(time.time()),"clie:","connection closed:",deleitem[3],"id:",deleitem[4])
					tryclose(deleitem[0])
					clielist.remove(deleitem)
			
			delelist = []
			for childpid in childlst:
				try:
					os.waitpid(childpid, os.WNOHANG)
				except:
					delelist.append(childpid)
			for deleitem in delelist:
				print(int(time.time()),"fork:","child exit:",deleitem)
				childlst.remove(deleitem)
			
			for clieitem in clielist:
				if (clieitem[1]):
					childpid = os.fork()
					if (childpid == 0):
						for sockitem in clielist:
							if (sockitem[0] != clieitem[0]):
								tryclose(sockitem[0]); tryclose(sockitem[1])
						for sockitem in servlist:
							if (sockitem[0] != clieitem[1]):
								tryclose(sockitem[0])
						if (clieitem[2]):
							try:
								clieitem[1].send(clieitem[2])
							except:
								pass
						childrwe([clieitem[0], clieitem[1]])
						sys.exit(0)
					else:
						print(int(time.time()),"fork:","child start:",childpid)
						delelist = []
						for sockitem in clielist:
							if (sockitem[0] == clieitem[0]):
								delelist.append(sockitem)
						for deleitem in delelist:
							tryclose(deleitem[0]); tryclose(deleitem[1])
							clielist.remove(deleitem)
						delelist = []
						for sockitem in servlist:
							if (sockitem[0] == clieitem[1]):
								delelist.append(sockitem)
						for deleitem in delelist:
							tryclose(deleitem[0])
							servlist.remove(deleitem)
						childlst.append(childpid)
	
	if (sys.argv[1] == "private"):
		servport = int(sys.argv[3])
		password = sys.argv[4]
		loclport = int(sys.argv[5])
		
		servobjc = None
		childlst = []
		while (1):
			forkitem = None
			if (servobjc == None):
				try:
					servaddr = socket.gethostbyaddr(sys.argv[2])
					servobjc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
					servobjc.connect((servaddr[2][0], servport))
					servobjc.send(password)
				except:
					servobjc = None
			if (servobjc == None):
				time.sleep(1)
				continue
			
			(readlist, writlist, errolist) = select.select([servobjc], [], [])
			
			if (servobjc in readlist):
				try:
					databuff = servobjc.recv(buffsize)
					clieaddr = socket.gethostbyaddr(sys.argv[2])
					clieobjc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
					clieobjc.connect((clieaddr[2][0], servport))
					clieobjc.send(databuff)
					middobjc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
					middobjc.connect(("127.0.0.1", loclport))
					forkitem = [clieobjc, middobjc, databuff]
				except:
					servobjc = None
			
			delelist = []
			for childpid in childlst:
				try:
					os.waitpid(childpid, os.WNOHANG)
				except:
					delelist.append(childpid)
			for deleitem in delelist:
				childlst.remove(deleitem)
			
			if (forkitem):
				childpid = os.fork()
				if (childpid == 0):
					childrwe([forkitem[0], forkitem[1]])
					sys.exit(0)
				else:
					tryclose(forkitem[0]); tryclose(forkitem[1])
					childlst.append(childpid)

if (__name__ == "__main__"):
	main()

[user1@public-server ~]$ ./fwbust.py public 61337 51337 abcxyz

[user2@private-server ~]$ ./fwbust.py private public.server.com 51337 abcxyz 22

[user3@local ~]$ ssh -p 61337 user2@public.server.com
[user2@private-server ~]$ hostname …

Figured it out yet? 🙂

Advertisements
Proof Of Concept Script – Allowing Incoming Server Connections Through An Outbound Client Connection Only (All Through An External Public Server)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s