挑战
我需要一个密码管理工具,它将被其他进程(各种脚本:python、php、perl 等)调用,它能够识别和验证调用者脚本以执行访问控制:要么返回密码返回或退出 -1
目前的实施
在研究了各种框架后,我决定使用能够处理 Keepass V1.X 后端数据库文件并构建我自己的访问控制覆盖python
的 's (因为以后可以对其进行自定义并集成到我们的 LDAP 以进行用户/组访问) keepassdb
. 访问控制是通过重载notes
每个条目的字段以包含允许访问密码的 SHA-256 哈希列表来完成的。(请注意,这也验证了脚本没有被任何人更改)
密码管理器使用参数调用,-p
该参数是被调用者脚本/应用程序的 PID,并将执行以下步骤:
- 从它自己的PID开始递归地“向上”查找并寻找父母。
1
在我们到达父 0的进程之前,必须找到调用者 PID。init
这样我们就可以确定我们知道谁调用了这个密码管理器实例。 - 获取该(父)进程的完整命令行并分析它以查找脚本语言,包括 python、perl、php、bash、bat、groovy 等(
shlex
用于此) - 找出脚本的绝对路径并计算其 SHA
- 将此与数据库值进行比较并查看它是否存在,如果存在,则允许脚本具有以标准格式在标准输出中返回的密码。如果不是,则以 -1 退出。
问题
上面的实现非常适合合法的脚本,但很容易混淆。让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()
现在,混淆上述函数的最简单方法是创建一个不带.sh
扩展名的 shell 脚本,该扩展名将caller.py
. sh 不使用它的参数,而是调用密码管理器查询条目e
。命令行看起来像这样fake_sh ./caller.py
,因此上面的代码返回 pass... 这是错误的做法。
问题
有人会认为这是很久以前解决的一个常见问题,没有程序员硬编码传递到脚本/应用程序中,但我做了几天的研究,我似乎无法找到任何以类似方式工作的东西。我知道这个问题比较开放,所以我会接受以下问题的答案:
- 我在重新发明轮子吗?是否有可以做类似事情的框架/软件?
- 这是依赖PID的正确方法吗?还有其他方法吗?
- 实施方面,发布的代码是否可以改进为更健壮且不易混淆?(
shlex
分析部分)