Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 非交互式进程的密码管理 挑战_Python_Security_Password Protection_Pid_Shlex - Fatal编程技术网

Python 非交互式进程的密码管理 挑战

Python 非交互式进程的密码管理 挑战,python,security,password-protection,pid,shlex,Python,Security,Password Protection,Pid,Shlex,我需要一个密码管理工具,它将被其他进程调用(各种脚本:python、php、perl等),它将能够识别和验证调用方脚本,以便执行访问控制:返回密码或退出-1 目前的执行情况 在研究了各种框架之后,我决定使用python的keepassdb,它能够处理keepassv1.X后端数据库文件,并构建我自己的访问控制覆盖层(因为稍后可以定制并集成到我们的LDAP中,以供用户/组访问)。访问控制通过重载每个条目的notes字段来完成,以包括允许访问密码的SHA-256哈希列表。(注意,这也验证了脚本没有被

我需要一个密码管理工具,它将被其他进程调用(各种脚本:python、php、perl等),它将能够识别和验证调用方脚本,以便执行访问控制:返回密码或退出-1

目前的执行情况 在研究了各种框架之后,我决定使用
python
keepassdb
,它能够处理keepassv1.X后端数据库文件,并构建我自己的访问控制覆盖层(因为稍后可以定制并集成到我们的LDAP中,以供用户/组访问)。访问控制通过重载每个条目的
notes
字段来完成,以包括允许访问密码的SHA-256哈希列表。(注意,这也验证了脚本没有被任何人更改)

使用
-p
参数调用密码管理器,该参数是被调用脚本/应用程序的PID,并将执行以下步骤:

  • 从它自己的PID开始递归地“向上”查找,并查找父对象。在到达进程
    1
    之前,必须找到调用方PID,该进程是父进程0的
    init
    。这样我们就可以确定是谁调用了这个密码管理器实例
  • 获取该(父)进程的完整命令行,并对其进行分析,寻找脚本语言,包括python、perl、php、bash、bat、groovy等(
    shlex
    用于此)
  • 计算脚本的绝对路径并计算其SHA
  • 将其与数据库值进行比较,查看它是否存在,如果存在,则允许脚本使用标准格式的stdout返回的密码。如果不是,则使用-1退出
  • 问题 上面的实现对于合法脚本非常有效,但很容易混淆。让
    caller.py
    成为允许访问特定条目
    e
    的脚本。运行它时,命令行看起来像python/path/to/caller.py arg1 arg2。解析命令行的代码是:

    cmd=walk\u ppids(pid)
    lg.debug(cmd)
    如果cmd为False:
    lg.错误(“PID%s不是我的父进程或根本不是进程!”%PID)
    系统出口(-1)
    cmd_parts=shlex.split(cmd)
    正在运行_script=“”
    对于cmd_零件中的p:
    如果重新搜索(\(php | py | pl | sh | groovy | bat)$),p,re.I):
    运行脚本=p
    打破
    如果未运行\u脚本:
    lg.error(“无法识别此脚本的名称/路径!”)
    系统出口(-1)
    running\u script=os.path.abspath(running\u script)
    lg.debug(“找到”+运行_脚本)
    phash=hash_文件(打开(运行_脚本'rb'),hashlib.sha256()
    
    父进程的命令行是通过以下方式获取的:

    os.popen(“ps-p%s-o args=“%ppid).read().strip()
    
    现在,混淆上述函数的最简单方法是创建一个shell脚本,而不使用
    .sh
    扩展名,该扩展名将
    caller.py
    作为第一个参数。sh不使用其参数,而是调用密码管理器查询条目
    e
    。命令行看起来像
    false\sh./caller.py
    ,因此上面的代码返回pass。。。这样做是错误的

    问题 有人会认为这是一个很早以前就解决的常见问题,没有程序员将硬编码传递到脚本/应用程序,但我做了几天的研究,似乎找不到任何类似的方法。我理解这个问题更具开放性,因此我将接受以下答案:

    • 我是在重新发明轮子吗?是否有类似的框架/软件
    • 依靠PIDs,这是正确的方法吗?还有别的办法吗
    • 在实现方面,发布的代码是否可以改进为更健壮、更容易混淆?(
      shlex
      分析部分)

    改进:使规则更加严格

    第一步是确认正确的扩展在正确的解释器上运行,这意味着
    caller.py
    不能在
    /bin/bash
    上运行

    python也可以利用类似的漏洞,例如 命令
    python-W./caller.py./myUberHack.py
    。如果命令行分析器向解释器查找第一个
    .py
    参数,则会认为
    caller.py
    正在运行。。。但事实并非如此

    为所有解释器构建所有调用规则太耗时了,所以我硬编码了这些假设。它们存储在
    元组中,每行为:

    (file extension, positional argument, interpreter first letters)
    
    exts=(
    (“.py”,1,“python”),
    (“.php”,2,“php”),
    (“.pl”,1,“perl”),
    (“.sh”,1,“/bin/bash”),#假设,我们只接受bash
    (“.groovy”,1,“groovy”),
    (“.rb”,1,“ruby”),
    )
    “”“将扩展名与位置参数和解释器匹配”“”
    
    现在的验证代码是:

    exts中i的
    :
    #检查指定的cmdline位置和扩展名
    如果cmd_parts[i[1]].strip().endswith(i[0]):
    lg.debug(“检查”+cmd_部分[i[1]])
    正在运行\u script=cmd\u parts[i[1]]
    #确保解释器与扩展名匹配
    如果运行的是_script.endswith(i[0]),而不是cmd_parts[0]。则使用(i[2])启动:
    lg.错误(“错误的解释者…走开…”)
    系统出口(-1)
    打破
    

    现在想不出比这更好的了……

    改进:使规则更加严格

    第一步是确认正确的扩展在正确的解释器上运行,这意味着
    caller.py
    不能在
    /bin/bash
    上运行

    python也可以利用类似的漏洞,例如 命令
    python-W./caller.py./myUberHack.py
    。如果命令行分析器向解释器查找第一个
    .py
    参数,则会认为
    caller.py
    正在运行。。。但事实并非如此

    <