我正在PostgreSQL上创建字典攻击工具。该工具的灵感来自m8r0wn-enumdb工具的工作。 Mikes工具针对MySQL和MSSQL。我的目标是使用与他所使用的相同的方法,但是修改操作和输出文件。脚本应该
1)读取包含目标和端口的CSV文件,每行127.0.0.1,3380一个。 2)当提供用户名和/或密码的列表时,它将在每个目标主机中循环寻找有效的凭据。默认情况下,它将使用新发现的凭据通过表或列名称上的关键字搜索在主机的数据库中搜索敏感信息。 3)然后可以提取此信息,并将其报告到JSON,.csv或.xlsx输出文件。
我有一个半功能代码,但是我怀疑PostgreSQL连接功能由于传递参数背后的逻辑而无法正常工作。我对如何最好地将工具结果显示为JSON文件的建议感兴趣。
我了解在Python中,我们有几个可用于连接和使用PostgreSQL的模块,其中包括:
Psycopg2
pg8000
py-postgresql
PyGreSQL
ocpgdb
bpgsql
SQLAlchemy
另请参阅https://www.a2hosting.co.za/kb/developer-corner/postgresql/connecting-to-postgresql-using-python
我尝试过的连接方法包括:
从psycopg2导入错误 conn = psycopg2.connect(主机=主机,dbname = db_name,用户= _user,密码= _pass,端口=端口)
conn = pg.DB(host = args.hostname,user = _user,passwd = _pass)
sudo pip安装pgdb
conn = pgdb.connect(host = args.hostname,user = _user,passwd = _pass)
我不确定如何在不破坏代码的情况下将不同的_user和_pass猜测传递到pyscopg2中。
我已导入以下库
import re
import psycopg2
from psycopg2 import Error
import pgdb
#import MySQLdb
import pymssql
import argparse
from time import sleep
from sys import exit, argv
from getpass import getpass
from os import path, remove
from openpyxl import Workbook
from threading import Thread, activeCount
PgSQL块如下:
##########################################
# PgSQL DB Class
##########################################
class pgsql():
def connect(self, host, port, user, passwd, verbose):
try:
con = pgdb.connect(host=host, port=port, user=user, password=passwd, connect_timeout=3)
con.query_timeout = 15
print_success("[*] Connection established {}:{}@{}".format(user,passwd,host))
return con
except Exception as e:
if verbose:
print_failure("[!] Login failed {}:{}@{}\t({})".format(user,passwd,host,e))
else:
print_failure("[!] Login failed {}:{}@{}".format(user, passwd, host))
return False
def db_query(self, con, cmd):
try:
cur = con.cursor()
cur.execute(cmd)
data = cur.fetchall()
cur.close()
except:
data = ''
return data
def get_databases(self, con):
databases = []
for x in self.db_query(con, 'SHOW DATABASES;'):
databases.append(x[0])
return databases
def get_tables(self, con, database):
tables = []
self.db_query(con, "USE {}".format(database))
for x in self.db_query(con, 'SHOW TABLES;'):
tables.append(x[0])
return tables
def get_columns(self, con, database, table):
# database var not used but kept to support mssql
columns = []
for x in self.db_query(con, 'SHOW COLUMNS FROM {}'.format(table)):
columns.append(x[0])
return columns
def get_data(self, con, database, table):
# database var not used but kept to support mssql
return self.db_query(con, 'SELECT * FROM {} LIMIT {}'.format(table, SELECT_LIMIT))
MSSQL如下:
# MSSQL DB Class
class mssql():
def connect(self, host, port, user, passwd, verbose):
try:
con = pymssql.connect(server=host, port=port, user=user, password=passwd, login_timeout=3, timeout=15)
print_success("[*] Connection established {}:{}@{}".format(user,passwd,host))
return con
except Exception as e:
if verbose:
print_failure("[!] Login failed {}:{}@{}\t({})".format(user,passwd,host,e))
else:
print_failure("[!] Login failed {}:{}@{}".format(user, passwd, host))
return False
def db_query(self, con, cmd):
try:
cur = con.cursor()
cur.execute(cmd)
data = cur.fetchall()
cur.close()
except:
data = ''
return data
def get_databases(self, con):
databases = []
for x in self.db_query(con, 'SELECT NAME FROM sys.Databases;'):
databases.append(x[0])
return databases
def get_tables(self, con, database):
tables = []
for x in self.db_query(con, 'SELECT NAME FROM {}.sys.tables;'.format(database)):
tables.append(x[0])
return tables
def get_columns(self, con, database, table):
columns = []
for x in self.db_query(con, 'USE {};SELECT column_name FROM information_schema.columns WHERE table_name = \'{}\';'.format(database, table)):
columns.append(x[0])
return columns
def get_data(self, con, database, table):
return self.db_query(con, 'SELECT TOP({}) * FROM {}.dbo.{};'.format(SELECT_LIMIT, database, table))
主要功能块:
def main(args):
try:
for t in args.target:
x = Thread(target=enum_db().db_main, args=(args, t,))
x.daemon = True
x.start()
# Do not exceed max threads
while activeCount() > args.max_threads:
sleep(0.001)
# Exit all threads before closing
while activeCount() > 1:
sleep(0.001)
except KeyboardInterrupt:
print("\n[!] Key Event Detected...\n\n")
exit(0)
if __name__ == '__main__':
version = '1.0.7'
try:
args = argparse.ArgumentParser(description=("""
{0} (v{1})
--------------------------------------------------
Brute force Juggernaut is a PgSQL brute forcing tool.**""").format(argv[0], version), formatter_class=argparse.RawTextHelpFormatter, usage=argparse.SUPPRESS)
user = args.add_mutually_exclusive_group(required=True)
user.add_argument('-u', dest='users', type=str, action='append', help='Single username')
user.add_argument('-U', dest='users', default=False, type=lambda x: file_exists(args, x), help='Users.txt file')
passwd = args.add_mutually_exclusive_group()
passwd.add_argument('-p', dest='passwords', action='append', default=[], help='Single password')
passwd.add_argument('-P', dest='passwords', default=False, type=lambda x: file_exists(args, x), help='Password.txt file')
args.add_argument('-threads', dest='max_threads', type=int, default=3, help='Max threads (Default: 3)')
args.add_argument('-port', dest='port', type=int, default=0, help='Specify non-standard port')
args.add_argument('-r', '-report', dest='report', type=str, default=False, help='Output Report: csv, xlsx (Default: None)')
args.add_argument('-t', dest='dbtype', type=str, required=True, help='Database types currently supported: mssql, pgsql')
args.add_argument('-c', '-columns', dest="column_search", action='store_true', help="Search for key words in column names (Default: table names)")
args.add_argument('-v', dest="verbose", action='store_true', help="Show failed login notices & keyword matches with Empty data sets")
args.add_argument('-brute', dest="brute", action='store_true', help='Brute force only, do not enumerate')
args.add_argument(dest='target', nargs='+', help='Target database server(s)')
args = args.parse_args()
# Put target input into an array
args.target = list_targets(args.target[0])
# Get Password if not provided
if not args.passwords:
args.passwords = [getpass("Enter password, or continue with null-value: ")]
# Define default port based on dbtype
if args.port == 0: args.port = default_port(args.dbtype)
# Launch Main
print("\nStarting enumdb v{}\n".format(version) + "-" * 25)
main(args)
except KeyboardInterrupt:
print("\n[!] Key Event Detected...\n\n")
exit(0)
I am aware that documentation states here http://initd.org/psycopg/docs/module.html states about how connection parameters can be specified. I would like to pass password guesses into the brute class and recursively try different combinations.
答案 0 :(得分:1)
PEP-8要求您给班级起一个名字
以大写字母开头,例如Pgsql
。
您提到pgsql connect()
方法无法正常工作,
但没有提供任何诊断信息,例如堆栈跟踪。
鉴于sqlalchemy层,您似乎工作太辛苦 已经很好地解决了数据库移植问题。 只需组装一个connect string 相应数据库包的名称, 然后让sqlalchemy负责其余的工作。
所有方法都接受con
作为参数。
您真的想将其作为对象属性self.con
加以考虑。
db_query()
方法显然假定
WHERE子句的参数已经出现在cmd
中,并用正确的引号引起来。
根据{{3}},
接受查询参数Little Bobby's mother很有意义,
而不用担心according to the API的潜力。