Honeypot done.

This commit is contained in:
trollhase 2013-08-22 09:44:10 +02:00
parent c1a08ba821
commit c968cf1e64

View file

@ -2,16 +2,169 @@ import SocketServer
import threading
import socket
from random import randint
import datetime
def mask(rights):
m = ""
if rights&4 != 0:
m += "r"
else:
m += "-"
if rights&2 != 0:
m += "w"
else:
m += "-"
if rights&1 != 0:
m += "x"
else:
m+= "-"
return m
class FSNode:
def __init__(self,name,owner="nobody",group="nobody",rights=384,size=0, iun=1):
self.name = name
self.owner = owner
self.group = group
self.rights = rights
self.size = size
self.parent = None
self.iun = iun
def is_dir(self):
return False
def is_file(self):
return False
def get_name(self):
return self.name
def get_size(self):
return self.size
def get_rights(self):
return self.rights
def get_last_change(self):
return datetime.date(2013,8,22)
#Thanks to a mumble session with lod :3
def get_boner(self):
return "large"
def get_parent_directory(self):
return self.parent
def get_owner(self):
return self.owner
def get_group(self):
return self.group
def get_imaginary_unicorn_number(self):
return self.iun
def get_mask(self):
m = ""
if self.is_dir():
m += "d"
else:
m += "-"
rights = self.get_rights()
m += mask((rights >> 6)&7)
m += mask((rights >> 3)&7)
m += mask(rights&7)
return m
def get_absolute_path(self):
if self.parent is None:
if self.is_dir():
return "/"
else:
return self.get_name()
else:
p = self.parent.get_absolute_path()
if p[-1] != "/":
p+= "/"
p+=self.get_name()
return p
class Directory(FSNode):
def __init__(self,name,owner="nobody",group="nobody",rights=384,size=4096,files=[]):
FSNode.__init__(self, name=name, owner=owner, group=group,rights=rights, size=size, iun=randint(2,10))
self.files = files
for f in self.files:
f.parent = self
def is_dir(self):
return True
def get_node(self,name):
for f in self.files:
if f.name == name:
return f
return None
class File(FSNode):
def __init__(self,name,owner="nobody",group="nobody",rights=384,size=4096, content=None):
FSNode.__init__(self, name=name, owner=owner, group=group,rights=rights, size=size, iun=1)
if content is None:
content = TextFileContent()
self.content = content
def is_file(self):
return True
def send_content(self,socket):
self.content.send_content(socket)
class FileContent:
def send_content(self, socket):
pass
class TextFileContent(FileContent):
def __init__(self, text=""):
self.text = text
def send_content(self, socket):
socket.send(self.text)
class FileFileContent(FileContent):
def __init__(self, filepath):
self.filepath = filepath
def send_content(self, socket):
fh = file(self.filepath,"r")
buf = fh.read(1024)
while len(buf) > 0:
socket.send(buf)
buf = fh.read(1024)
class HoneypotFileContent(FileContent):
def send_content(self, socket):
for i in range(4000):
socket.send('HONEYPOT');
class URandomFileContent(FileFileContent):
def __init__(self):
FileFileContent.__init__(self, "/dev/urandom")
class DataConnection:
def run(self, dchandler):
pass
class PassiveDataConnection(DataConnection):
def __init__(self, port):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind(("",port))
self.connection = None
threading.Thread(target=self.waitForConnection).start()
def waitForConnection(self):
@ -19,6 +172,8 @@ class PassiveDataConnection(DataConnection):
self.connection, _ = self.socket.accept()
def run(self, dchandler):
while self.connection is None:
pass
threading.Thread(target=self.runHandler, args=(dchandler,) ).start()
def runHandler(self, dchandler):
@ -26,9 +181,9 @@ class PassiveDataConnection(DataConnection):
self.connection.close()
class ActiveDataConnection(DataConnection):
def __init__(self, host, port):
def __init__(self, addr):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect( (host,port) )
self.socket.connect( addr )
def run(self, dchandler):
threading.Thread(target=self.runHandler, args=(dchandler,)).start()
@ -106,10 +261,94 @@ class EnteringPassiveModeMessage(FTPMessage):
def __init__(self,addrtuple):
FTPMessage.__init__(self,"227","Entering Passive Mode %s." % addrtuple)
class BeginDirectoryListingMessage(FTPMessage):
def __init__(self):
FTPMessage.__init__(self,"150","Here comes the directory listing.")
class EndDirectoryListingMessage(FTPMessage):
def __init__(self):
FTPMessage.__init__(self,"226","Directory send OK.")
class WorkingDirectoryMessage(FTPMessage):
def __init__(self, workingDirectory):
FTPMessage.__init__(self,"257","\"%s\" is the current directory" % workingDirectory)
class ChangeDirectorySuccessfulMessage(FTPMessage):
def __init__(self):
FTPMessage.__init__(self,"250","command successful")
class ChangeDirectoryFailedMessage(FTPMessage):
def __init__(self):
FTPMessage.__init__(self,"550","No such directory")
class InvalidParametersMessage(FTPMessage):
def __init__(self):
FTPMessage.__init__(self,"504","Command not implemented for that parameter")
class InvalidPortCommandMessage(FTPMessage):
def __init__(self):
FTPMessage.__init__(self,"500","Illegal port command")
class CommandSuccessfulMessage(FTPMessage):
def __init__(self,cmd):
FTPMessage.__init__(self,"200","%s command successful" % cmd)
class OperationNotPermittedMessage(FTPMessage):
def __init__(self):
FTPMessage.__init__(self,"550","Operation not permitted")
class TypeSetMessage(FTPMessage):
def __init__(self,val):
FTPMessage.__init__(self,"200","Type set to %s" % val)
class BeginFileRetrieve(FTPMessage):
def __init__(self,node):
FTPMessage.__init__(self,"150","Opening ASCII mode data connection for %s (%d bytes)" % (node.get_name(),node.get_size()))
class EndFileRetrieve(FTPMessage):
def __init__(self):
FTPMessage.__init__(self,"226","Transfer complete")
# Data Connection Handler
class HeloHandler:
class NListHandler:
def __init__(self, directory, handler):
self.directory = directory
self.handler = handler
def handle(self, socket):
socket.send("Hello World")
for f in self.directory.files:
socket.send(f.get_name()+"\n")
class ListHandler:
def __init__(self, directory, handler):
self.directory = directory
self.handler = handler
def handle(self, socket):
self.handler.send( BeginDirectoryListingMessage() )
for f in self.directory.files:
socket.send( "%10s %3d %-8s %-8s %8d %3s %2d %5d %s\n" % (
f.get_mask(),
f.get_imaginary_unicorn_number(),
f.get_owner(),
f.get_group(),
f.get_size(),
f.get_last_change().strftime("%b"),
f.get_last_change().day,
f.get_last_change().year,
f.get_name()
) )
self.handler.send( EndDirectoryListingMessage() )
class RetrieveHandler:
def __init__(self, node, handler):
self.node = node
self.handler = handler
def handle(self, socket):
self.handler.send( BeginFileRetrieve(self.node) )
self.node.send_content(socket)
self.handler.send( EndFileRetrieve() )
# State classes
class State:
@ -160,12 +399,70 @@ class AuthorizedState(MainState):
port = handler.createPassiveDataConnection()
handler.debug("Created passive data connection")
handler.send( EnteringPassiveModeMessage( self.addrtuple("127.0.0.1",port) ) )
elif message.cmd == "HELO":
handler.debug("Running Helo on data connection")
if handler.runDataConnection(HeloHandler()):
elif message.cmd in ["DELE","RMD","RNFR","RNTO","STOR"]:
handler.send( OperationNotPermittedMessage() )
elif message.cmd == "RETR":
node = handler.get_node(message.parameter)
if node.is_file():
handler.runDataConnection( RetrieveHandler(node, handler) )
else:
handler.send( OperationNotPermittedMessage() )
elif message.cmd == "PORT":
hp = message.parameter.split(",")
if len(hp) != 6:
handler.debug( "Invalid port information" )
handler.send( InvalidParametersMessage() )
return
if int(hp[0]) == 10 or int(hp[0]) == 127 or int(hp[0]) == 192: #Prevent local scanning
handler.send( InvalidPortCommandMessage() )
return
addr = ( ".".join(hp[:4]), int(hp[4])<<8+int(hp[5]) )
handler.createActiveDataConnection(addr)
handler.debug("Created active data connection to %s:%d" % addr)
handler.send( CommandSuccessfulMessage("PORT") )
elif message.cmd == "LIST":
handler.debug("Listing current directory")
if handler.runDataConnection(ListHandler(handler.currentDirectory, handler)):
handler.debug("successful")
else:
handler.debug("failed")
elif message.cmd == "NLST":
handler.debug("Listing current directory (simple)")
if handler.runDataConnection(NListHandler(handler.currentDirectory)):
handler.debug("successful")
else:
handler.debug("failed")
elif message.cmd == "CWD":
node = handler.get_node(message.parameter)
if node is None or not node.is_dir():
handler.debug("Error trying to switch into non-existent directory")
handler.send( ChangeDirectoryFailedMessage() )
else:
handler.currentDirectory = node
handler.debug("Changed working directory to "+node.get_absolute_path())
handler.send( ChangeDirectorySuccessfulMessage() )
elif message.cmd == "CDUP":
node = handler.currentDirectory.get_parent_directory()
if node is None or not node.is_dir():
handler.debug("Error trying to switch to parent directory")
else:
handler.debug("Changed working directory to "+node.get_absolute_path())
handler.currentDirectory = node
handler.send( ChangeDirectorySuccessfulMessage() )
elif message.cmd == "PWD":
handler.send( WorkingDirectoryMessage(handler.currentDirectory.get_absolute_path()) )
elif message.cmd == "TYPE":
if message.parameter == "A":
handler.send( TypeSetMessage(message.parameter) )
else:
handler.send( InvalidCommandMessage("TYPE") )
elif message.cmd == "NOOP":
handler.send( CommandSuccessfulMessage("NOOP") )
else:
MainState.process(self, handler, message)
@ -181,7 +478,7 @@ class LineReader:
while pos != -1:
line = self.buf[:pos]
if line[-1] == "\r":
line = line[:-2]
line = line[:-1]
yield line
self.buf = self.buf[pos+1:]
pos = self.buf.find("\n")
@ -191,15 +488,39 @@ class FTPHandler(SocketServer.BaseRequestHandler):
print ("[%s] " % self.client_address[0]) + text
def send(self, message):
self.request.send( str(message) )
line = str(message)
self.debug("< "+line)
self.request.send( line )
def createPassiveDataConnection(self):
port = randint(60000,63000)
self.connection = PassiveDataConnection(port)
return port
def createActiveDataConnection(self,port):
self.connection = ActiveDataConnection(self.client_address[0],port)
def createActiveDataConnection(self,addr):
self.connection = ActiveDataConnection(addr)
def get_node(self,path):
if path == "/":
return self.rootDirectory
if path[0] == "/":
cnode = self.rootDirectory
path = path[1:]
else:
cnode = self.currentDirectory
if path[-1] == "/":
path = path[:-1]
parts = path.split("/")
for part in parts:
if cnode == None or not cnode.is_dir():
return None
cnode = cnode.get_node(part)
return cnode
def runDataConnection(self, dchandler):
if self.connection is None:
@ -210,6 +531,8 @@ class FTPHandler(SocketServer.BaseRequestHandler):
return True
def handle(self):
self.currentDirectory = self.rootDirectory
self.connection = None
self.state = NonAuthorizedState()
@ -230,6 +553,7 @@ class FTPHandler(SocketServer.BaseRequestHandler):
linereader.push(data)
for line in linereader.get_lines():
self.debug("> "+line)
message = FTPMessage.parse(line)
self.state.process(self,message)
@ -238,6 +562,63 @@ class FTPHandler(SocketServer.BaseRequestHandler):
handler = FTPHandler
handler.authorizer = AnonymousAuthorizer()
server = SocketServer.ThreadingTCPServer(("",1234),handler)
recdir = Directory("recursive",files=[
File("is")
])
recdir.files.append(recdir)
server.serve_forever()
handler.rootDirectory = Directory("",files=[
Directory("etc", files=[
File("passwd",content=URandomFileContent()),
File("shadow",content=URandomFileContent()),
recdir
]),
Directory("usr", files=[
Directory("share"),
Directory("bin", files=[
File("sh")
])
]),
Directory("home", files=[
Directory("john",owner="john"),
Directory("jane",owner="jane"),
Directory("peter",owner="peter")
]),
Directory("root", files=[
Directory("ssh",files=[
File("authorized_keys",content=URandomFileContent())
]),
File("db.dump", content=URandomFileContent())
]),
Directory("dev"),
Directory("mnt"),
Directory("var", files=[
Directory("www")
]),
Directory("bin"),
Directory("tmp"),
Directory("lost+found"),
Directory("boot"),
Directory("lib"),
Directory("lib32"),
Directory("proc"),
Directory("src"),
File("vmlinuz",size=4000000),
Directory("selinux"),
Directory("opt"),
File("initrd.img",size=4000000)
])
port = 1234
while True:
try:
server = SocketServer.ThreadingTCPServer(("",port),handler)
print "Listening on port %d" % port
server.serve_forever()
break
except Exception:
if port < 1500:
port += 1
else:
print "Failed to find a port"
break