如果需要,防止 Python 中的连接字符串污染攻击
Prevent connection string pollution attacks in Python, if needed
我想 return 在传递数据库的用户 ID 和密码时预定义查询的结果。
查询是常量,因此不是基本的 SQL 注入场景。
但是,允许用户指定将 .format()
连接到连接字符串中的用户名和密码是否会造成任何漏洞?
(我发现 a source 表明它确实如此——主要是我对 sqlalchemy.create_engine
和 pymongo.MongoClient
感兴趣,但对任何常见数据存储和 python 感兴趣模块。)
如果需要,我应该如何修改以下示例以清理输入?
from sqlalchemy import create_engine # requires module: psycopg2
import urllib.parse
import pandas as pd
import getpass
CONSTANT_QUERY_STRING = "SELECT * FROM table1;"
DB_URI = 'postgresql://{db_user}:{db_password}@postgres.acme.com:5432/acme_db'
class DbConnector:
def __init__(self, db_uri, db_user, db_password):
self.uri = db_uri.format(db_user=db_user, db_password=urllib.parse.quote_plus(db_password))
def get_data(self, query):
engine = create_engine(self.uri)
df = pd.read_sql_query(query, con=engine)
engine.dispose()
return df
if __name__ == "__main__":
userid = input('User: ')
password = getpass.getpass('Password for {}:'.format(userid))
df = DbConnector(DB_URI,userid,password).get_data(CONSTANT_QUERY_STRING)
if df:
print("Here's your data!")
print(df)
与任何类型的任何注入一样 - 它取决于攻击者能够注入的特殊字符和可接受的 URI 格式。
假设我注入以下值:
用户名:user
密码:
密码@malicious.server.com:5432/acme_db?
或
密码@malicious.server.com:5432/acme_db#
结果会怎样?
postgresql://用户:密码@malicious.server.com:5432/acme_db?@postgres.acme.com:5432/acme_db
postgresql://用户:密码@malicious.server.com:5432/acme_db#@postgres.acme.com:5432/acme_db
您的应用程序将连接到不同的数据库,并且行为可能会被完全修改。我不知道这些 URI 格式是否会被接受,但问题是:为什么要冒险?
您知道有效的用户名和密码结构是什么,只需对其进行验证并对您允许的特殊字符进行编码(如果您希望密码中包含任何字符)。可能 URI 编码会完成这项工作。
我想 return 在传递数据库的用户 ID 和密码时预定义查询的结果。
查询是常量,因此不是基本的 SQL 注入场景。
但是,允许用户指定将 .format()
连接到连接字符串中的用户名和密码是否会造成任何漏洞?
(我发现 a source 表明它确实如此——主要是我对 sqlalchemy.create_engine
和 pymongo.MongoClient
感兴趣,但对任何常见数据存储和 python 感兴趣模块。)
如果需要,我应该如何修改以下示例以清理输入?
from sqlalchemy import create_engine # requires module: psycopg2
import urllib.parse
import pandas as pd
import getpass
CONSTANT_QUERY_STRING = "SELECT * FROM table1;"
DB_URI = 'postgresql://{db_user}:{db_password}@postgres.acme.com:5432/acme_db'
class DbConnector:
def __init__(self, db_uri, db_user, db_password):
self.uri = db_uri.format(db_user=db_user, db_password=urllib.parse.quote_plus(db_password))
def get_data(self, query):
engine = create_engine(self.uri)
df = pd.read_sql_query(query, con=engine)
engine.dispose()
return df
if __name__ == "__main__":
userid = input('User: ')
password = getpass.getpass('Password for {}:'.format(userid))
df = DbConnector(DB_URI,userid,password).get_data(CONSTANT_QUERY_STRING)
if df:
print("Here's your data!")
print(df)
与任何类型的任何注入一样 - 它取决于攻击者能够注入的特殊字符和可接受的 URI 格式。 假设我注入以下值:
用户名:user
密码: 密码@malicious.server.com:5432/acme_db?
或
密码@malicious.server.com:5432/acme_db#
结果会怎样?
postgresql://用户:密码@malicious.server.com:5432/acme_db?@postgres.acme.com:5432/acme_db
postgresql://用户:密码@malicious.server.com:5432/acme_db#@postgres.acme.com:5432/acme_db
您的应用程序将连接到不同的数据库,并且行为可能会被完全修改。我不知道这些 URI 格式是否会被接受,但问题是:为什么要冒险?
您知道有效的用户名和密码结构是什么,只需对其进行验证并对您允许的特殊字符进行编码(如果您希望密码中包含任何字符)。可能 URI 编码会完成这项工作。