【问题标题】:How to modify the PostgreSQL psycopg to accept variables instead of values如何修改 PostgreSQL psycopg 以接受变量而不是值
【发布时间】:2019-09-04 21:13:02
【问题描述】:

我正在 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

从 psycopg2 导入错误 conn = psycopg2.connect(host=host, dbname=db_name, user=_user, password=_pass, port=port)

导入 pg

conn = pg.DB(host=args.hostname, user= _user, passwd= _pass)

sudo pip install pgdb

导入 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.

【问题讨论】:

    标签: python-3.x postgresql python-2.7 brute-force


    【解决方案1】:

    PEP-8 要求您给课程起个名字 以大写字母开头,例如Pgsql。 您提到 pgsql connect() 方法无法正常工作, 但没有提供任何诊断信息,例如堆栈跟踪。

    鉴于 sqlalchemy 层,您似乎工作太努力了 已经很好地解决了数据库移植问题。 只需组装一个connect string,以 适当的数据库包的名称, 让 sqlalchemy 处理剩下的事情。

    您的所有方法都接受con 作为参数。 你真的想把它作为对象属性self.con 考虑出来。

    db_query() 方法显然假设 WHERE 子句的参数已在cmd 中正确引用。 根据Little Bobby's mother, 接受查询参数according to the API 是有意义的, 而不是担心SQL injection的潜力。

    【讨论】:

      猜你喜欢
      • 2017-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 2021-10-04
      • 2013-01-22
      • 1970-01-01
      相关资源
      最近更新 更多