adding some new scripts and updated hack(le)s

master
brent s 4 years ago
parent 6f450ab68f
commit 33043a3499
  1. 4
      aif/scripts/post/sshkeys.py
  2. 84
      mysql/tblinfo.py
  3. 132
      net/ssh/audit.py
  4. 14
      ref/python.tips_tricks_and_dirty_hacks

@ -12,9 +12,9 @@ def copyKeys(keystring, user = 'root'):
homedir = os.path.expanduser('~{0}'.format(user))
sshdir = '{0}/.ssh'.format(homedir)
authfile = '{0}/authorized_keys'.format(sshdir)
os.makedirs(sshdir, mode = 0o700, exist_ok = True)
with open(authfile, 'a') as f:
f.write(keystring)
os.makedirs(sshdir, mode = 0o700, exist_ok = True)
for basedir, dirs, files in os.walk(sshdir):
os.chown(basedir, uid, gid)
os.chmod(basedir, 0o700)
@ -28,4 +28,4 @@ def main():
copyKeys(keys.read().decode('utf-8'))

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

@ -0,0 +1,84 @@
#!/usr/bin/env python3

import argparse
import configparser
import copy
import os
import pymysql

mysql_internal = ['information_schema', 'mysql']

# Not used, but could be in the future.
stat_hdrs = ['Name', 'Engine', 'Version', 'Row_format', 'Rows', 'Avg_row_length', 'Data_length',
'Max_data_length', 'Index_length', 'Data_free', 'Auto_increment', 'Create_time',
'Update_time', 'Check_time', 'Collation', 'Checksum', 'Create_options', 'Comment']
tblinfo_hdrs = ['Field', 'Type', 'Null', 'Key', 'Default', 'Extra']

def get_info(db, internal = False):
dbs = {}
if os.path.isfile(os.path.expanduser('~/.my.cnf')):
_cfg = configparser.ConfigParser(allow_no_value = True)
_cfg.read(os.path.expanduser('~/.my.cnf'))
_cfg = dict(_cfg['client'])
_cfg['ssl'] = {}
if 'host' not in _cfg:
_cfg['host'] = 'localhost'
conn = pymysql.connect(**_cfg, cursorclass = pymysql.cursors.DictCursor)
else:
raise RuntimeError('Need mysql creds at ~/.my.cnf')
cur = conn.cursor()
if not db:
cur.execute("SHOW DATABASES")
db = [row['Database'] for row in cur.fetchall()]
if not internal:
for d in mysql_internal:
try:
db.remove(d)
except ValueError: # Not in the list; our user probably doesn't have access
pass
else:
db = [db]
for d in db:
dbs[d] = {}
cur.execute("SHOW TABLES FROM `{0}`".format(d))
for tbl in [t['Tables_in_{0}'.format(d)] for t in cur.fetchall()]:
dbs[d][tbl] = {}
# Status
cur.execute("SHOW TABLE STATUS FROM `{0}` WHERE Name = %s".format(d), (tbl, ))
dbs[d][tbl]['_STATUS'] = copy.deepcopy(cur.fetchone())
# Columns
dbs[d][tbl]['_COLUMNS'] = {}
#cur.execute("DESCRIBE {0}.{1}".format(d, tbl))
cur.execute("SHOW COLUMNS IN `{0}` FROM `{1}`".format(tbl, d))
for row in cur.fetchall():
colNm = row['Field']
dbs[d][tbl]['_COLUMNS'][colNm] = {}
for k in [x for x in tblinfo_hdrs if x is not 'Field']:
dbs[d][tbl]['_COLUMNS'][colNm][k] = row[k]
cur.close()
conn.close()
return(dbs)

def parseArgs():
args = argparse.ArgumentParser()
args.add_argument('-i', '--internal',
dest = 'internal',
action = 'store_true',
help = ('If specified, include the MySQL internal databases '
'(mysql, information_schema, etc.); only used if -d is not specified'))
args.add_argument('-d', '--database',
dest = 'db',
default = None,
help = 'If specified, only list table info for this DB')
return(args)

def main():
args = vars(parseArgs().parse_args())
dbs = get_info(args['db'], internal = args['internal'])
#import json
#print(json.dumps(dbs, indent = 4, sort_keys = True, default = str))
import pprint
pprint.pprint(dbs)

if __name__ == '__main__':
main()

@ -0,0 +1,132 @@
#!/usr/bin/env python3

import argparse
import paramiko
import socket


class SSHAuthInfo(object):
def __init__(self, target, port = 22, banner = True, ciphers = True, digests = True, kex = True, key_types = True,
methods = True, hostkeys = True, version = True):
self.target = target
self.port = int(port)
self.info = {'target': self.target,
'port': self.port,
'banner': banner,
'ciphers': ciphers,
'digests': digests,
'kex': kex,
'key_types': key_types,
'methods': methods,
'hostkeys': hostkeys,
'version': version}
self._ssh = None
if any((ciphers, banner, methods, digests, kex, key_types)): # These need an SSH connection.
self._ssh_dummy()
if banner:
self.getBanner()
if hostkeys:
self.getHostkeys()
if version:
self.getVersion()
self._close()

def _ssh_dummy(self):
self._ssh = paramiko.Transport((self.target, self.port))
self._ssh.connect()
try:
self._ssh.auth_none('')
except paramiko.ssh_exception.BadAuthenticationType as err:
secopts = self._ssh.get_security_options()
print(secopts.key_types)
if self.info['methods']:
# https://stackoverflow.com/a/1257769
self.info['methods'] = err.allowed_types
if self.info['ciphers']:
self.info['ciphers'] = list(secopts.ciphers)
if self.info['digests']:
self.info['digests'] = list(secopts.digests)
if self.info['kex']:
self.info['kex'] = list(secopts.kex)
if self.info['key_types']:
self.info['key_types'] = list(secopts.key_types)
return()

def getBanner(self):
self.info['banner'] = None
# https://github.com/paramiko/paramiko/issues/273#issuecomment-225058645 doesn't seem to work.
# But https://github.com/paramiko/paramiko/pull/58#issuecomment-63857078 did!
self.info['banner'] = self._ssh.get_banner()
return()

def getHostkeys(self):
# TODO: how the hell do I get *all* hostkeys served?
self.info['hostkeys'] = {}
k = self._ssh.get_remote_server_key()
self.info['hostkeys'][k.get_name()] = k.get_base64()
return()

def getVersion(self):
self.info['version'] = None
s = socket.socket()
s.connect((self.target, self.port))
try:
# 8192 bytes is kind of overkill considering most are probably going to be around 20 bytes or so.
self.info['version'] = s.recv(8192)
except Exception as e:
pass
return()

def _close(self):
if self._ssh:
self._ssh.close()

def parseArgs():
args = argparse.ArgumentParser()
args.add_argument('-b', '--no-banner',
action = 'store_false',
dest = 'banner',
help = 'Do not gather the SSH banner')
args.add_argument('-c', '--no-ciphers',
action = 'store_false',
dest = 'ciphers',
help = 'Do not gather supported ciphers')
args.add_argument('-d', '--no-digests',
action = 'store_false',
dest = 'digests',
help = 'Do not gather supported digests')
args.add_argument('-m', '--no-methods',
action = 'store_false',
dest = 'methods',
help = 'Do not gather supported auth methods')
args.add_argument('-k', '--no-hostkeys',
action = 'store_false',
dest = 'hostkeys',
help = 'Do not gather hostkeys')
args.add_argument('-x', '--no-kex',
action = 'store_false',
dest = 'kex',
help = 'Do not gather supported key exchanges')
args.add_argument('-t', '--no-key-types',
action = 'store_false',
dest = 'key_types',
help = 'Do not gather supported key types')
args.add_argument('-v', '--no-version',
action = 'store_false',
dest = 'version',
help = 'Do not gather SSH version')
args.add_argument('-p', '--port',
default = 22,
help = 'The port on target that the SSH daemon is running on. Default is 22')
args.add_argument('target',
help = 'The server to run the check against')
return(args)

def main():
args = vars(parseArgs().parse_args())
i = SSHAuthInfo(**args)
import pprint
pprint.pprint(i.info)

if __name__ == '__main__':
main()

@ -118,3 +118,17 @@ To issue an equivalent of "reset" command in linux, assuming console is ANSI-com
print('\x1bc', end = '')

###############################################################################


To get the default route via pyroute2,
----
import socket
from pyroute2 import IPDB
ip = IPDB()
def_rt = ip.routes['default'] # a route object
iface = ip.interfaces[def_rt.oif] # an interface object. name is e.g. iface.ifname, IPs are in tuple-of-tuples iface.ipaddr, etc.
gw = def_rt.gateway # etc.
ip.release()
----

###############################################################################

Loading…
Cancel
Save