我需要一个密码管理工具,它将被其他进程调用(所有类型的脚本:python,php,perl等),它将能够识别和验证调用者脚本以执行访问控制:返回密码或退出-1
在研究了各种框架之后,我决定使用python
的{{1}}能够处理Keepass V1.X后端数据库文件并构建自己的访问控制覆盖(因为这可以在以后自定义并集成到我们的LDAP以进行用户/组访问)。通过重载每个条目的keepassdb
字段来完成访问控制,以包括允许访问密码的SHA-256哈希列表。 (请注意,这也验证了任何人都不会更改脚本)
使用notes
参数调用密码管理器,该参数是被调用者脚本/应用程序的PID,并将执行以下步骤:
-p
进程1
之前,必须找到调用者PID。这样我们就知道我们知道谁调用了这个密码管理器实例。init
用于此)上述实现对于合法脚本很有效,但很容易混淆它。让shlex
成为允许访问特定条目caller.py
的脚本。运行命令行看起来像e
。解析命令行的代码是:
python /path/to/caller.py arg1 arg2
使用以下方法获取父进程的命令行:
cmd = walk_ppids(pid)
lg.debug(cmd)
if cmd is False:
lg.error("PID %s is not my parent process or not a process at all!" % pid)
sys.exit(-1)
cmd_parts = shlex.split(cmd)
running_script = ""
for p in cmd_parts:
if re.search("\.(php|py|pl|sh|groovy|bat)$", p, re.I):
running_script = p
break
if not running_script:
lg.error("Cannot identify this script's name/path!")
sys.exit(-1)
running_script = os.path.abspath(running_script)
lg.debug("Found "+running_script)
phash = hash_file(open(running_script, 'rb'), hashlib.sha256())
现在,混淆上述功能的最简单方法是创建一个没有os.popen("ps -p %s -o args=" % ppid).read().strip()
扩展名的shell脚本,该扩展名作为.sh
的第一个参数。 sh不使用其参数,而是调用密码管理器查询条目caller.py
。命令行看起来像e
,因此上面的代码返回传递...这是错误的事情。
有人会认为这是很久以前解决的一个常见问题,没有程序员硬编码传递到脚本/应用程序,但我做了一些研究几天,我似乎找不到任何有用的东西类似的方式。我知道这个问题更开放,所以我会接受以下答案:
fake_sh ./caller.py
分析部分)答案 0 :(得分:0)
改进:使规则更严格
第一步是确认在正确的解释器上运行正确的扩展名,这意味着caller.py
无法在/bin/bash
上运行。
类似的漏洞可以被python利用,例如
命令python -W ./caller.py ./myUberHack.py
。查找解释器的第一个.py
参数的命令行分析器会认为caller.py
正在运行......哪个不是。
为所有解释器构建所有调用规则会非常耗时,因此我对这些假设进行了硬编码。它们存储在tuple
中,每行都是:
(file extension, positional argument, interpreter first letters)
exts = (
(".py", 1, "python"),
(".php", 2, "php"),
(".pl", 1, "perl"),
(".sh", 1, "/bin/bash"), # Assumption, we accept only bash
(".groovy", 1, "groovy"),
(".rb", 1, "ruby"),
)
"""Matching extensions to positional arguments and interpreters"""
验证码现在是:
for i in exts:
# Check the specified cmdline position and extension
if cmd_parts[i[1]].strip().endswith(i[0]):
lg.debug("Checking "+cmd_parts[i[1]])
running_script = cmd_parts[i[1]]
# Make sure that the interpretter matches the extension
if running_script.endswith(i[0]) and not cmd_parts[0].startswith(i[2]):
lg.error("Wrong interpretter... go away...")
sys.exit(-1)
break
目前想不出更好的事情......