first commit
This commit is contained in:
235
src/ssh-backdoor
Executable file
235
src/ssh-backdoor
Executable file
@@ -0,0 +1,235 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from datetime import timedelta, datetime
|
||||
from tabulate import tabulate
|
||||
import random
|
||||
import sqlite3
|
||||
import time, os, sys
|
||||
|
||||
def setup_options():
|
||||
''' Setup the command line options '''
|
||||
from argparse import ArgumentParser
|
||||
|
||||
parser=ArgumentParser(description="Alive notifier.")
|
||||
parser.add_argument(
|
||||
"--db",
|
||||
action = 'store',
|
||||
dest = 'DB',
|
||||
default = '/tmp/ssh-backdoor.sqlite',
|
||||
type = str,
|
||||
help = "Sqlite file for database: %(default)s"
|
||||
)
|
||||
# TODO --connect (replace ssh-local-connect)
|
||||
parser.add_argument(
|
||||
"--clear",
|
||||
action = 'store_true',
|
||||
dest = 'clear',
|
||||
default = False,
|
||||
help = "Clear the database of everything, first"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--list","-l",
|
||||
action = 'store_true',
|
||||
dest = 'list',
|
||||
default = False,
|
||||
help = "List ports"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--list-names",
|
||||
action = 'store_true',
|
||||
dest = 'list_names',
|
||||
default = False,
|
||||
help = "List alive host names only"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--query",
|
||||
action = 'store',
|
||||
dest = 'query',
|
||||
default = None,
|
||||
type = str,
|
||||
help="Query port for an id"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--quiet", "-q",
|
||||
action = 'store_true',
|
||||
dest = 'quiet',
|
||||
default = False,
|
||||
help = "Quiet operation: %(default)s"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--wait", "-w",
|
||||
action = 'store_true',
|
||||
dest = 'wait',
|
||||
default = False,
|
||||
help = "Enter infinite loop"
|
||||
)
|
||||
parser.add_argument(
|
||||
action = 'store',
|
||||
dest = 'id',
|
||||
default = None ,
|
||||
type = str,
|
||||
nargs = '?',
|
||||
help="Id name for port"
|
||||
)
|
||||
options=parser.parse_args()
|
||||
return options
|
||||
|
||||
|
||||
class DataBase:
|
||||
def __init__(self, DB):
|
||||
self.alive = 7 * 24 * 3600 # 7 days
|
||||
self.DBfile = DB
|
||||
self.conn = None
|
||||
self.db = None
|
||||
if not os.path.exists(self.DBfile):
|
||||
self.createDB()
|
||||
self.conn_init()
|
||||
self.clean_db()
|
||||
|
||||
def clear(self):
|
||||
self.db = self.conn.cursor()
|
||||
self.db.execute("DELETE FROM ports")
|
||||
self.conn_end()
|
||||
|
||||
def conn_init(self):
|
||||
self.conn = sqlite3.connect(self.DBfile)
|
||||
self.db = self.conn.cursor()
|
||||
self.conn.text_factory = str
|
||||
|
||||
def conn_end(self):
|
||||
self.conn.commit()
|
||||
#self.conn.close()
|
||||
|
||||
def createDB(self):
|
||||
self.conn_init()
|
||||
self.db.execute('CREATE TABLE ports (\
|
||||
id TEXT PRIMARY KEY,\
|
||||
host TEXT, \
|
||||
port INTEGER,\
|
||||
pid INTEGER,\
|
||||
die INTEGER,\
|
||||
date INTEGER)')
|
||||
self.conn_end()
|
||||
|
||||
def clean_db(self):
|
||||
self.db = self.conn.cursor()
|
||||
self.db.execute("SELECT id,port,date,pid,host FROM ports")
|
||||
for row in self.db.fetchall():
|
||||
age = int(time.time() - row[2])
|
||||
running = self.is_running(row[3])
|
||||
if running:
|
||||
continue
|
||||
if age < self.alive:
|
||||
continue
|
||||
self.db.execute("DELETE FROM ports WHERE id = ?", (row[0],))
|
||||
self.conn_end()
|
||||
|
||||
def die(self):
|
||||
""" kills process, and parents, if set to die """
|
||||
pass
|
||||
|
||||
def update(self, id):
|
||||
port = self.get_port(id)
|
||||
if port == None:
|
||||
port = self.new_port()
|
||||
|
||||
self.db = self.conn.cursor()
|
||||
self.db.execute("INSERT OR REPLACE INTO ports(id,port,date,pid,host) \
|
||||
VALUES(?,?,?,?,?)",(
|
||||
id,
|
||||
port,
|
||||
int(time.time()),
|
||||
self.get_pid(),
|
||||
os.getenv("SSH_CLIENT","-").split(" ")[0]
|
||||
)
|
||||
)
|
||||
self.conn_end()
|
||||
return port
|
||||
|
||||
def list(self):
|
||||
self.db = self.conn.cursor()
|
||||
self.db.execute("SELECT id,port,host,date,pid FROM ports ORDER BY id")
|
||||
rows = []
|
||||
for row in self.db:
|
||||
row = list(row)
|
||||
row[3] = self.human_age(row[3])
|
||||
row.append(self.is_running(row[4]))
|
||||
# ~ row.append("ssh-nosave -p %d localhost"%( row[1], ) )
|
||||
rows.append(row)
|
||||
return rows
|
||||
|
||||
|
||||
def human_age(self, sec):
|
||||
sec = timedelta(seconds = time.time() - sec)
|
||||
d = datetime(1,1,1) + sec
|
||||
return "%d %02d:%02d:%02d" % (d.day - 1, d.hour, d.minute, d.second)
|
||||
|
||||
|
||||
def is_running(self, pid):
|
||||
try:
|
||||
os.kill(pid, 0)
|
||||
except OSError:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def get_pid(self):
|
||||
return os.getppid()
|
||||
|
||||
def get_port(self, id):
|
||||
self.db = self.conn.cursor()
|
||||
self.db.execute("SELECT port FROM ports WHERE id = ?", (id,))
|
||||
result = self.db.fetchall()
|
||||
if len(result) == 0:
|
||||
return None
|
||||
return result[0][0]
|
||||
|
||||
def new_port(self):
|
||||
self.db = self.conn.cursor()
|
||||
while True:
|
||||
port = random.randint(22200, 22400)
|
||||
self.db.execute("SELECT port FROM ports WHERE port = ?", (port,))
|
||||
result = self.db.fetchall()
|
||||
if len(result) == 0:
|
||||
return port
|
||||
|
||||
if __name__ == "__main__":
|
||||
opts=setup_options()
|
||||
db = DataBase(opts.DB)
|
||||
start_time = time.time()
|
||||
if opts.clear:
|
||||
db.clear()
|
||||
if opts.list_names:
|
||||
for row in db.list():
|
||||
if row[5]:
|
||||
print(row[0])
|
||||
sys.exit(0)
|
||||
if opts.list:
|
||||
print(tabulate(
|
||||
db.list(),
|
||||
headers = ['Id','Port','Host','Age','PID','Alive']
|
||||
))
|
||||
if opts.query != None:
|
||||
port = db.get_port(opts.query)
|
||||
if port == None:
|
||||
sys.exit(1)
|
||||
print(port)
|
||||
sys.exit(0)
|
||||
if opts.id != None:
|
||||
print(db.update(opts.id))
|
||||
if opts.wait:
|
||||
sys.stderr.write(
|
||||
" Connected\r"
|
||||
)
|
||||
while True:
|
||||
if time.time() - start_time > 3600:
|
||||
sys.exit(0)
|
||||
db.update(opts.id)
|
||||
for i in range(10):
|
||||
db.die()
|
||||
time.sleep(3 + random.random())
|
||||
sys.stderr.write(
|
||||
" " +
|
||||
time.strftime("%c") +
|
||||
"\r"
|
||||
)
|
||||
Reference in New Issue
Block a user